如何让SplFileObject的fgetcsv不将\视为转义字符?
解决SplFileObject::fgetcsv()将\视为转义字符的问题
PHP内置的fgetcsv(包括SplFileObject中的实现)默认会把反斜杠\当作转义字符,这会导致CSV文件中的\"被解析为文本的一部分,进而破坏整个CSV的结构,出现跨行解析、单元格内容混乱的问题。由于没有直接的配置项可以关闭这个转义行为,你可以通过以下两种方式解决:
方法1:预处理行内容,修正CSV转义规则
根据CSV标准(RFC 4180),双引号的正确转义方式是用另一个双引号包裹(即""),而非\"。我们可以先读取每行内容,将\"替换为"",再用str_getcsv解析:
$file = new SplFileObject('1.txt'); while (!$file->eof()) { $line = $file->fgets(); // 将不符合标准的\"替换为标准的"" $correctedLine = str_replace('\"', '""', $line); $row = str_getcsv($correctedLine, ';'); print_r($row); }
处理后,原内容中的"foo\"会被转为"foo"",解析后单元格内容为foo",同时不会破坏后续的CSV分隔结构。
方法2:自定义CSV解析逻辑,忽略反斜杠转义
如果需要完全绕过内置函数的转义逻辑,可以自己实现简单的CSV解析,仅将双引号作为单元格包裹标记,分号作为分隔符,忽略反斜杠的转义作用:
function customCsvParse($line, $delimiter = ';') { $rows = []; $currentCell = ''; $inQuotes = false; $lineLength = strlen($line); for ($i = 0; $i < $lineLength; $i++) { $char = $line[$i]; // 切换双引号包裹状态 if ($char === '"') { $inQuotes = !$inQuotes; continue; } // 仅在未被双引号包裹时,将分号视为分隔符 if ($char === $delimiter && !$inQuotes) { $rows[] = $currentCell; $currentCell = ''; continue; } $currentCell .= $char; } // 添加最后一个单元格,去除换行符 $rows[] = rtrim($currentCell, "\n\r"); return $rows; } // 使用自定义解析函数处理文件 $file = new SplFileObject('1.txt'); while (!$file->eof()) { $line = $file->fgets(); $row = customCsvParse($line, ';'); print_r($row); }
内容的提问来源于stack exchange,提问作者Roman
相关产品推荐
相关产品推荐

