站長資訊網
最全最豐富的資訊網站

如何解決php trim 亂碼問題

php trim亂碼是因為在執行rtrim時,會將0x81去掉,導致出現亂碼,其解決辦法就是通過“mb_rtrim($tag, "、",$encoding)”方法解決亂碼即可。

如何解決php trim 亂碼問題

本文操作環境:windows7系統、PHP7.1版,DELL G3電腦

首先運行以下代碼:

$tag = "互聯網產品、"; $text = rtrim($tag, "、"); print_r($text);

我們可能以為會得到的結果是互聯網產品,實際結果是互聯網產?。為什么會這樣呢?

科普

PHP 里使用mb_前綴的都是多字節函數 http://php.net/manual/zh/ref….

比如

$str = "abcd"; print_r(strlen($str).""); // 4 print_r(mb_strlen($str).""); // 4 $str = "周夢康"; print_r(strlen($str).""); // 9 print_r(mb_strlen($str).""); // 3

mb_系列函數是以“多個字節組成的一個字符”為顆粒度來操作的,不帶mb_則是按實際的字節數來操作的。

原理

trim 函數文檔

string trim ( string $str [, string $character_mask = " " ] )

該函數不是多字節函數,也就是說,漢字這樣的多字節字符,會拿其頭或尾的單字節來和后面的$character_mask對應的char數組進行匹配,如果在后面的數組中,則刪掉,繼續匹配。比如:

echo ltrim("bcdf","abc"); // df

如下面的 demo 中的函數string_print_char所示:

、由0xe3 0x80 0x81三字節組成,

品由0xe5 0x93 0x81三字節組成。

所以在執行rtrim的時候,通過字節比對,會將0x81去掉,導致了最后出現了亂碼。

【推薦學習:《PHP視頻教程》】

源碼探究

查看 PHP7 的源碼,然后提煉出下面的小 demo ,方便大家一起學習,其實PHP源碼的學習并不難,每天進步一點點。

// // main.c // trim // // Created by 周夢康 on 2017/10/18. // Copyright ? 2017年 周夢康. All rights reserved. // #include <stdio.h> #include <stdlib.h> #include <string.h> void string_print_char(char *str); void php_charmask(unsigned char *input, size_t len, char *mask); char *ltrim(char *str,char *character_mask); char *rtrim(char *str,char *character_mask); int main(int argc, char const *argv[]) { printf("%s",ltrim("bcdf","abc")); string_print_char("品"); // e5 93 81 string_print_char("、"); // e3 80 81 printf("%s",rtrim("互聯網產品、","、")); return 0; } char *ltrim(char *str,char *character_mask) { char *res; char mask[256]; register size_t i; int trimmed = 0; size_t len = strlen(str); php_charmask((unsigned char*)character_mask, strlen(character_mask), mask); for (i = 0; i < len; i++) { if (mask[(unsigned char)str[i]]) { trimmed++; } else { break; } } len -= trimmed; str += trimmed; res = (char *) malloc(sizeof(char) * (len+1)); memcpy(res,str,len); return res; } char *rtrim(char *str,char *character_mask) { char *res; char mask[256]; register size_t i; size_t len = strlen(str); php_charmask((unsigned char*)character_mask, strlen(character_mask), mask); if (len > 0) { i = len - 1; do { if (mask[(unsigned char)str[i]]) { len--; } else { break; } } while (i-- != 0); } res = (char *) malloc(sizeof(char) * (len+1)); memcpy(res,str,len); return res; } void string_print_char(char *str) { unsigned long l = strlen(str); for (int i=0; i < l; i++) { printf("%02hhx ",str[i]); } printf(""); } void php_charmask(unsigned char *input, size_t len, char *mask) { unsigned char *end; unsigned char c; memset(mask, 0, 256); for (end = input+len; input < end; input++) { c = *input; mask[c]= 1; } }

如果覺得 demo 還不夠清晰的,復制下來,自己執行一次吧~

C 語言基礎較差的同學也不用擔心,我準備后面專門寫一個PHP小白學習 C 語言的系列入門短文哈。

解決方案

那么我們就依葫蘆畫瓢,用 php 本身的多字節函數來實現下吧:

function mb_rtrim($string, $trim, $encoding) { $mask = []; $trimLength = mb_strlen($trim, $encoding); for ($i = 0; $i < $trimLength; $i++) { $item = mb_substr($trim, $i, 1, $encoding); $mask[] = $item; } $len = mb_strlen($string, $encoding); if ($len > 0) { $i = $len - 1; do { $item = mb_substr($string, $i, 1, $encoding); if (in_array($item, $mask)) { $len--; } else { break; } } while ($i-- != 0); } return mb_substr($string, 0, $len, $encoding); } mb_internal_encoding("UTF-8"); $tag = "互聯網產品、"; $encoding = mb_internal_encoding(); print_r(mb_rtrim($tag, "、",$encoding));

當然你也可以使用正則來做。通過上面的函數學習,單字節函數和多字節函數,你學會了嗎?

PHP7 相關源碼

PHP_FUNCTION(trim) { php_do_trim(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3); } PHP_FUNCTION(rtrim) { php_do_trim(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2); } PHP_FUNCTION(ltrim) { php_do_trim(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } static void php_do_trim(INTERNAL_FUNCTION_PARAMETERS, int mode) { zend_string *str; zend_string *what = NULL; ZEND_PARSE_PARAMETERS_START(1, 2) Z_PARAM_STR(str) Z_PARAM_OPTIONAL Z_PARAM_STR(what) ZEND_PARSE_PARAMETERS_END(); ZVAL_STR(return_value, php_trim(str, (what ? ZSTR_VAL(what) : NULL), (what ? ZSTR_LEN(what) : 0), mode)); } PHPAPI zend_string *php_trim(zend_string *str, char *what, size_t what_len, int mode) { const char *c = ZSTR_VAL(str); size_t len = ZSTR_LEN(str); register size_t i; size_t trimmed = 0; char mask[256]; if (what) { if (what_len == 1) { char p = *what; if (mode & 1) { for (i = 0; i < len; i++) { if (c[i] == p) { trimmed++; } else { break; } } len -= trimmed; c += trimmed; } if (mode & 2) { if (len > 0) { i = len - 1; do { if (c[i] == p) { len--; } else { break; } } while (i-- != 0); } } } else { php_charmask((unsigned char*)what, what_len, mask); if (mode & 1) { for (i = 0; i < len; i++) { if (mask[(unsigned char)c[i]]) { trimmed++; } else { break; } } len -= trimmed; c += trimmed; } if (mode & 2) { if (len > 0) { i = len - 1; do { if (mask[(unsigned char)c[i]]) { len--; } else { break; } } while (i-- != 0); } } } } else { if (mode & 1) { for (i = 0; i < len; i++) { if ((unsigned char)c[i] <= ' ' && (c[i] == ' ' || c[i] == '' || c[i] == '' || c[i] == ' ' || c[i] == '' || c[i] == '')) { trimmed++; } else { break; } } len -= trimmed; c += trimmed; } if (mode & 2) { if (len > 0) { i = len - 1; do { if ((unsigned char)c[i] <= ' ' && (c[i] == ' ' || c[i] == '' || c[i] == '' || c[i] == ' ' || c[i] == '' || c[i] == '')) { len--; } else { break; } } while (i-- != 0); } } } if (ZSTR_LEN(str) == len) { return zend_string_copy(str); } else { return zend_string_init(c, len, 0); } } /* {{{ php_charmask * Fills a 256-byte bytemask with input. You can specify a range like 'a..z', * it needs to be incrementing. * Returns: FAILURE/SUCCESS whether the input was correct (i.e. no range errors) */ static inline int php_charmask(unsigned char *input, size_t len, char *mask) { unsigned char *end; unsigned char c; int result = SUCCESS; memset(mask, 0, 256); for (end = input+len; input < end; input++) { c=*input; if ((input+3 < end) && input[1] == '.' && input[2] == '.' && input[3] >= c) { memset(mask+c, 1, input[3] - c + 1); input+=3; } else if ((input+1 < end) && input[0] == '.' && input[1] == '.') { /* Error, try to be as helpful as possible: (a range ending/starting with '.' won't be captured here) */ if (end-len >= input) { /* there was no 'left' char */ php_error_docref(NULL, E_WARNING, "Invalid '..'-range, no character to the left of '..'"); result = FAILURE; continue; } if (input+2 >= end) { /* there is no 'right' char */ php_error_docref(NULL, E_WARNING, "Invalid '..'-range, no character to the right of '..'"); result = FAILURE; continue; } if (input[-1] > input[2]) { /* wrong order */ php_error_docref(NULL, E_WARNING, "Invalid '..'-range, '..'-range needs to be incrementing"); result = FAILURE; continue; } /* FIXME: better error (a..b..c is the only left possibility?) */ php_error_docref(NULL, E_WARNING, "Invalid '..'-range"); result = FAILURE; continue; } else { mask[c]=1; } } return result; } /* }}} */

贊(0)
分享到: 更多 (0)
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
国产亚洲精品看片在线观看| 久久久久久久久无码精品亚洲日韩 | 蜜臀AV无码精品人妻色欲| 久久久久亚洲精品无码蜜桃| 2022国产精品自在线拍国产| 精品人妻少妇嫩草AV无码专区| 思思久久99热免费精品6| 日韩在线不卡免费视频一区| 国产精品亚洲二区在线| 日韩精品福利视频一区二区三区| 一区二区亚洲精品精华液| 国产精品喷水在线观看| 久久机热这里只有精品无需| 久久久精品国产sm调教网站| 日韩精品亚洲人成在线观看| 久久久精品免费国产四虎| 国语自产少妇精品视频蜜桃| 99在线热播精品免费99热| 久久人搡人人玩人妻精品首页| 国产精品青草视频免费播放| 8x福利精品第一导航| 亚洲国产成人精品女人久久久 | 国产精品久久久久久久小说| 国产精品久久久香蕉| 国产a视频精品免费观看| 91麻豆精品一二三区在线| 亚洲精品国产福利在线观看| 91精品免费久久久久久久久| 亚洲精品亚洲人成在线播放| 国产香蕉一区二区精品视频| 国产精品蜜芽在线观看| 国产精品白丝在线观看有码 | 日韩电影无码A不卡| 国产91精品久久久久久久| 日韩在线视频播放免费视频完整版| 国产剧情精品在线观看| 国产91精品不卡在线| 国产福利电影一区二区三区,日韩伦理电影在线福 | 久久国产精品无码一区二区三区| 亚洲欧洲国产精品你懂的| 99re国产精品|