PHP按行拆分文件按列分组时如何修剪空行导致的false无效条目
问题背景
现有如下splitfile函数,功能为逐行读取目标文件内容,将每行按|字符拆分后,根据拆分得到的列数对行数据进行分组:
public function splitfile(Request $request) { $groups = []; $session = Session::where('id', $request->id)->first(); $file = Storage::get($session->filepath); $separator = "\r\n"; $line = strtok($file, $separator); while ($line) { $line = strtok($separator); $splitted = explode("|", $line); $cols = count($splitted); $groups[$cols][] = $line; } return response()->json($groups); }
函数运行后返回的分组结果出现异常:
[24: [line1, line2...], 1: [false]]
返回结果中存在键为1、值为[false]的异常分组,已知该异常和文件内空行有关,需要修剪去除这类无效空行条目。
故障原因
异常由两个逻辑问题共同导致:
strtok遍历顺序错误:初始化时已经通过strtok拿到了文件第一行内容,进入循环后第一时间再次调用strtok,会直接跳过文件第一行;当strtok遍历到文件末尾时会返回false,该返回值没有经过校验就直接进入后续拆分流程。- 空值未过滤:
explode("|", false)会触发PHP的自动类型转换,将false转为空字符串处理,拆分后得到的数组长度为1,因此生成了键为1的异常分组;同时文件首尾的空行、仅含空白字符的无效行也没有被过滤,会被计入分组结果。
修复方案
调整strtok遍历逻辑,增加空行校验步骤,修复后代码如下:
public function splitfile(Request $request) { $groups = []; $session = Session::where('id', $request->id)->first(); $file = Storage::get($session->filepath); $separator = "\r\n"; $line = strtok($file, $separator); // 严格判断返回值,避免"0"这类等效false的有效行被误过滤 while ($line !== false) { // 去除行首尾所有空白字符(换行、空格、制表符) $trimmedLine = trim($line); // 非空行才进入分组逻辑 if ($trimmedLine !== '') { $splitted = explode("|", $trimmedLine); $cols = count($splitted); $groups[$cols][] = $trimmedLine; } // 循环末尾取下一行,避免跳过首行、避免把末尾false带入处理 $line = strtok($separator); } return response()->json($groups); }
可选兼容性优化
如果需要兼容Linux(\n换行)、旧Mac系统(\r换行)的文件格式,可以替换strtok逻辑,用正则匹配所有类型的换行符拆分行,兼容性更强:
public function splitfile(Request $request) { $groups = []; $session = Session::where('id', $request->id)->first(); $file = Storage::get($session->filepath); // 兼容所有操作系统换行格式拆分文件行 $lines = preg_split('/\r\n|\r|\n/', $file); foreach ($lines as $line) { $trimmedLine = trim($line); if ($trimmedLine === '') { continue; } $splitted = explode("|", $trimmedLine); $cols = count($splitted); $groups[$cols][] = $trimmedLine; } return response()->json($groups); }
内容的提问来源于stack exchange,提问作者Katy Del Mary
相关产品推荐
相关产品推荐

