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

如何解決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一区二区三区| 久久精品国产一区二区三| 国产亚洲精品美女| 欧美激情国产精品视频一区二区 | 国产精品成人不卡在线观看| 无码精品国产一区二区三区免费| 亚洲一区二区三区在线观看精品中文| 国产精品小视频免费无限app| 日韩精品无码人妻一区二区三区| 亚洲日韩中文字幕| 亚洲欭美日韩颜射在线二| 国产免费无遮挡精品视频| 国产精品亚洲专区在线播放| 日本精品3d动漫一区二区| 成人精品一区二区不卡视频| 久草热8精品视频在线观看| 无码专区人妻系列日韩精品少妇| 国产精品美女久久福利网站| 99热这里只有精品9| 日韩视频在线精品视频免费观看 | 一本色道久久88亚洲精品综合| 精品国精品无码自拍自在线| 亚洲国产精品无码久久久| 2020国产精品视频| 亚洲精品永久www忘忧草| 91久久精品无码一区二区毛片| 亚洲国产精品日韩在线观看| 精品丝袜国产自在线拍亚洲| 无码精品尤物一区二区三区| 精品国产日韩久久亚洲| 亚洲精品国产高清在线观看| 十八禁无遮挡99精品国产| 精品国产乱码久久久久久郑州公司 | 国自产拍 高清精品| 国产亚洲精品影视在线| 91免费精品国自产拍在线不卡| 久9re热视频这里只有精品| 国产麻豆剧果冻传媒免精品费网站 | 日韩激情淫片免费看| 亚洲AⅤ永久无码精品AA| 精品人妻少妇一区二区|