iT邦幫忙

0

[筆記,php,csv]排除字串中未知特殊字元

需求:
我要讀取一個csv檔,然後判斷某個id的內容有無更新
該csv檔用逗號區隔,中文沒有雙引號包起來

嘗試:
既然是csv,直接上fgetcsv,
但因為中文沒有雙引號包起來,導致資料分隔錯誤,
連續好幾個欄位被當成一個欄位....

所以乾脆fgets自己來...

狀況:
其中一個欄位出了問題....
在判斷有無更新時,讀取csv的字串跟原本的字串比較
在字串比對時肉眼上看
if ("-2.16.886.101.90028.20002-20017-" == "-2.16.886.101.90028.20002-20017-")
理論上是相同的,但就是進不去if

我肉眼看,單步執行查看變數看到的內容皆是一樣,卻怎麼都是false !!??
嗯?

輸出長度長度應為32,但讀取出來卻是35 !!??
嗯? 有不可見的特殊未知字元藏在其中!!

那來排除特殊字元吧...

處理方式

下面是各種嘗試

$t = $v['oid'];
echo $t . ' len:'. strlen($t)   . "\xA";
// -2.16.886.101.90028.20002-20017- len:35

$t = trim($v['oid']);
echo $t . ' len:'. strlen($t)   . "\xA";
// -2.16.886.101.90028.20002-20017- len:35

$t = trim($v['oid'], " \t\n\r\0\x0B \z\000\x00\u0000\a\b\v\f\e");
echo $t . ' len:'. strlen($t)   . "\xA";
// -2.16.886.101.90028.20002-20017- len:35

$t =  preg_replace("/\W/", '', $v['oid']);
echo $t . ' len:'. strlen($t)   . "\xA";
// 216886101900282000220017 len:24
// 總算把那個怪符號弄掉了,但也誤殺要留的'-',regex怎麼改...不熟,有前輩知道的話麻煩告知一下

$t = bin2hex($target);
echo $t . ' len:'. strlen($t)   . "\xA";
// 2d322e31362e3838362e3130312e39303032382e32303030322d32303031372d len:64

$t = hex2bin(bin2hex($target));
echo $t . ' len:'. strlen($t)   . "\xA";
// -2.16.886.101.90028.20002-20017- len:32
// 轉碼出去再轉回來字串長度就正確了,內容看起來也沒問題

輸出結果
輸出到cmd上可以看到前面多個空白,但若透過IDE單步執行查看變數內容、或輸出到文字檔的話,啥都沒看到...

-2.16.886.101.90028.20002-20017- len:35
-2.16.886.101.90028.20002-20017- len:35
-2.16.886.101.90028.20002-20017- len:35
216886101900282000220017 len:24
2d322e31362e3838362e3130312e39303032382e32303030322d32303031372d len:64
-2.16.886.101.90028.20002-20017- len:32

結論
透過轉碼,轉碼出去再轉回來字串長度就正確了,內容看起來也沒問題
-> 沒效....只是在cmd上看起來有解決而已XD

透過 淺水員 的支援得知是UTF-8 BOM
知道原因後就簡單了 PHP 判斷/移除 BOM(UTF-8) 解決~

**疑問 **
這個特殊字元到底是啥??
-> 感謝 淺水員 的支援,是 UTF-8 BOM


1 則留言

2
淺水員
iT邦研究生 4 級 ‧ 2020-08-06 14:21:42

這個出來會是什麼?

echo bin2hex($v['oid']);
看更多先前的回應...收起先前的回應...
舜~ iT邦高手 1 級 ‧ 2020-08-06 14:23:35 檢舉

2d322e31362e3838362e3130312e39303032382e32303030322d32303031372d

舜~ iT邦高手 1 級 ‧ 2020-08-06 14:24:17 檢舉

從長度來看特殊字元好像已經不見了XD

淺水員 iT邦研究生 4 級 ‧ 2020-08-06 14:29:26 檢舉

那這樣呢?

$arr=unpack('C*', $v['oid']);
var_dump($arr);

或是用 ord 一個一個列出來...

舜~ iT邦高手 1 級 ‧ 2020-08-06 14:45:35 檢舉

print_r 結果 Array(
[1] => 239 [2] => 187 [3] => 191
[4] => 45 [5] => 50 [6] => 46
[7] => 49 [8] => 54 [9] => 46
[10] => 56 [11] => 56 [12] => 54
[13] => 46 [14] => 49 [15] => 48
[16] => 49 [17] => 46 [18] => 57
[19] => 48 [20] => 48 [21] => 50
[22] => 56 [23] => 46 [24] => 50
[25] => 48 [26] => 48 [27] => 48
[28] => 50 [29] => 45 [30] => 50
[31] => 48 [32] => 48 [33] => 49
[34] => 55 [35] => 45
)

淺水員 iT邦研究生 4 級 ‧ 2020-08-06 14:55:23 檢舉

前三個是 EF BB BF
原來是UTF8 的 BOM XD

舜~ iT邦高手 1 級 ‧ 2020-08-06 15:00:05 檢舉

!!原來如此,感恩您的解惑

我要留言

立即登入留言