Laravel中使用PHP读取CSV文件返回二进制字符串问题
解决Laravel读取CSV时输出含空字节单元素数组的问题
问题原因
输出里的ÿþ是UTF-16LE编码的字节顺序标记(BOM),\x00是UTF-16编码的空字节,同时内容中的\t说明这其实是制表符分隔的文件(TSV),并非逗号分隔的标准CSV。而fgetcsv默认以逗号为分隔符,且不支持UTF-16这类双字节编码,因此会把整行内容识别为单个元素,同时保留编码相关的乱码。
解决方案
方法1:读取后转编码+指定制表符分隔
直接读取文件内容并转换编码,再按制表符分割数据:
$filePath = Storage::path('email_ingested_data/data/Report.csv'); // 读取文件并将UTF-16LE编码转为UTF-8 $content = mb_convert_encoding(file_get_contents($filePath), 'UTF-8', 'UTF-16LE'); // 按行拆分内容 $lines = explode("\n", trim($content)); // 用制表符作为分隔符解析表头 $header = str_getcsv($lines[0], "\t"); dd($header);
方法2:通过编码转换流读取
利用PHP的过滤流直接转换编码,同时指定分隔符:
$filePath = Storage::path('email_ingested_data/data/Report.csv'); // 打开带编码转换的文件流,将UTF-16LE转为UTF-8 $file = fopen("php://filter/read=convert.iconv.UTF-16LE/UTF-8/resource=$filePath", 'r'); // 设置制表符为分隔符,读取表头 fgetcsv($file, 0, "\t"); $csv = fgetcsv($file, 0, "\t"); dd($csv);
方法3:Laravel Storage直接处理
用Laravel的Storage门面读取内容后处理编码和分隔:
$content = Storage::get('email_ingested_data/data/Report.csv'); // 移除UTF-16的BOM并转换编码为UTF-8 $content = preg_replace('/^\x{FEFF}/u', '', mb_convert_encoding($content, 'UTF-8', 'UTF-16LE')); // 按行拆分并逐行用制表符解析 $rows = array_map(function($row) { return str_getcsv($row, "\t"); }, explode("\n", trim($content))); dd($rows[0]);
验证提示
- 可通过IDE查看文件编码(比如VS Code右下角的编码标识),确认是否为UTF-16LE,确保转换编码参数匹配。
- 必须指定制表符
"\t"作为解析分隔符,否则工具会默认用逗号拆分,导致整行被识别为单个元素。
内容的提问来源于stack exchange,提问作者Elliott Coe
相关产品推荐
相关产品推荐

