php 換行符問題
背景
公司有個業務需要用戶上傳csv文件,里面的內容以逗號(,)分隔 ,然后每一行代表一條數據,業務代碼讀取數據根據業務規則入庫。
有用戶反饋,自己上傳的csv文件“符合規范”,但上傳后提示數據為空
問題定位
拿到用戶的csv文件,用notepad++打開文件,發現換行符和期望的\r\n ,不一樣,用戶的csv文件換行符是\r,跟用戶確認后,明確用戶用的mac電腦,因為mac和windows上換行符不一致到這該問題,業務代碼是用php編寫的,默認無法識別\r,把csv里面的內容當作一行來處理,導致業務報錯
解決
- 先緊急解決用戶的問題
拿到用戶的csv文件后,手動替換\r為\r\n,引導用戶重新上傳,解決問題先
- 修改業務代碼,解決該問題,有兩種方案
- 修改php.ini文件,打開**auto_detect_line_endings **配置,具體如下:
auto_detect_line_endings = On
- 在業務代碼中,加入如下代碼:
ini_set("auto_detect_line_endings", true);
原理
unix系列用 \n
windows系列用 \r\n
mac用 \r
\n是換行,英文是New line,表示使光標到行首
\r是回車,英文是Carriage return,表示使光標下移一格
\r\n表示回車換行
我們在平時使用電腦時,已經習慣了回車和換行一次搞定,敲一個回車鍵,即是回車,又是換行。
Unix系統里,每行結尾只有“<換行>”,即"\n";
Windows系統里面,每行結尾是“<回車><換行>”,即“\r\n”;
Mac系統里,每行結尾是“<回車>”,即"\r";
一個直接后果是,Unix/Mac系統下的文件在Windows里打開的話,所有文字會變成一行;
而Windows里的文件在Unix/Mac下打開的話,在每行的結尾可能會多出一個^M符號。
auto_detect_line_endings
boolean
當設為 On 時,PHP 將檢查通過 fgets() 和 file() 取得的數據中的行結束符號是符合 Unix,MS-DOS,還是 Macintosh 的習慣。
這使得 PHP 可以和 Macintosh 系統交互操作,但是默認值是 Off,因為在檢測第一行的 EOL 習慣時會有很小的性能損失,而且在 Unix 系統下使用回車符號作為項目分隔符的人們會遭遇向下不兼容的行為。
參考資料
https://blog.csdn.net/qq_40395278/article/details/81199281 (推薦)
https://www.php.net/manual/zh/filesystem.configuration.php