求助:PHP中\SplFileObject迭代时为何重复键0?
为什么SplFileObject会出现重复键的问题?
嘿,我来帮你理清这个困惑!你遇到的重复键问题,根源在于手动调用fgets()时,SplFileObject的key()不会自动更新行号。
问题原因
SplFileObject本身是一个迭代器(实现了Iterator接口),它的key()方法返回的是当前迭代位置的行号。但当你直接调用fgets()读取内容时,这个操作只会移动文件指针读取一行,并不会触发迭代器的next()逻辑——也就是不会自动递增key()的值。所以每次循环里,你拿到的key()都是同一个,自然就会出现重复键的情况。
解决方案
有两种简单的方式可以解决这个问题:
方案1:直接用foreach遍历SplFileObject(推荐)
利用SplFileObject自身的迭代器逻辑,它会自动处理key()的递增,完全不用手动操心:
$str = <<<'EOD' Line 1 Line 2 Line 3 Line 4 Line 5 EOD; $file = new \SplFileObject('data://text/plain;base64,' . base64_encode($str)); $iterator = call_user_func(function (\SplFileObject $file) { foreach ($file as $key => $line) { yield [$key => $line]; } }, $file); // 测试输出 foreach ($iterator as $item) { print_r($item); }
方案2:手动调用next()更新key
如果你一定要保留while循环的写法,记得每次读取行之后调用next(),让key()递增到下一行的编号:
$str = <<<'EOD' Line 1 Line 2 Line 3 Line 4 Line 5 EOD; $file = new \SplFileObject('data://text/plain;base64,' . base64_encode($str)); $iterator = call_user_func(function (\SplFileObject $file) { while (!$file->eof()) { $key = $file->key(); $line = $file->fgets(); // 避免最后一行可能为空的情况,过滤无效内容 if ($line !== false) { yield [$key => $line]; } // 手动触发迭代器前进,更新key值 $file->next(); } }, $file); // 测试输出 foreach ($iterator as $item) { print_r($item); }
额外提示
注意eof()的判断:如果文件最后一行是空行,fgets()可能会返回false,所以加个$line !== false的判断可以避免生成无效的yield项。
内容的提问来源于stack exchange,提问作者Curtis
相关产品推荐
相关产品推荐

