1

转到更新以阅读现在的实际问题。Bert Peters 提交的第一个答案已经解决了旧问题。

老问题: 我有几个名为 file.1.txt、file.2.txt、file.3.txt 的文件……我正在使用 SplFileObject 读取第一个文件并使用 foreach 循环遍历其内容:

$file = new SplFileObject("file.1.txt");
foreach ($file as $row) {
  // ...
}

其他文件可能会被读取,也可能不会被读取,这取决于我正在读取的第一个文件的内容。在所有情况下,都应该只有一个文件(file.2.txt 或 file.3.txt)可以在下一步中使用。所以在 foreach 循环中的某个地方有 if 语句来处理这个问题。

所有文件都具有相同的结构,因此出现了问题。我不想创建新的 foreach 来读取下一个文件 - 正如我所写的那样,它可能根本不需要,所以我想使用现有的 foreach 而不是编写新的。是否有可能用其他文件的内容覆盖 $file 变量并仅使用一个 foreach 或任何其他循环对其进行迭代?例如:

foreach ($file as $row) {
  // ...
  if ($contentContainsSomething) {
    $file = new SplFileObject("file.2.txt");
    // somehow reset foreach to read file.2.txt from start
  }
}

我不想用goto语句来解决这个问题。递归似乎是合适的解决方案,但如果有办法动态更改循环中的对象,我更喜欢这个解决方案。

更新: 如“老问题”中所述,所有使用的文件(file.1.txt、file.2.txt、...)都具有相同的结构,所以我不想编写更多相同的循环并复制代码. 相反,我使用了来自@Danack 的代码(他在 SO 聊天中建议),这已经是解决方案的一部分。这是无需任何升级即可读取更多文件的基本代码:

$path = "file.1.txt";
$whileCounter = 0;
while ($path != null) {
  $file = new SplFileObject($path);
  $file->setFlags(SplFileObject::READ_CSV);
  $file->setCsvControl("\t");
  $path = null;
  foreach ($file as $rowKey => $row) {
    // echo row  }
  $path = "file.2.txt";
  if ($whileCounter > 0) {
    break; // solution to stop loop, just for now
  }
  $whileCounter++;
}

因此,此代码可以正常工作并按预期输出文件的行。问题是当我想用 seek() 方法读取文件的下一行时,因为我想对附加到下一行的一些信息做出决定。因此,如果我使用 seek($rowKey + 1) 帮助我获取下一行数据(我在行更改时使用 $file->current() )然后我调用 seek($rowKey) 到上一行,然后下一个文件将输出第一行两次,第二行将被遗漏。第三行以及之后的所有内容都打印得很好。这是通过以下代码实现的问题:

$path = "file.1.txt";
$whileCounter = 0;
while ($path != null) {
  $file = new SplFileObject($path);
  $file->setFlags(SplFileObject::READ_CSV);
  $file->setCsvControl("\t");
  $path = null;
  foreach ($file as $rowKey => $row) {
    if ($whileCounter > 0) {
      var_dump($row);
      echo "<br>";
    }
    $file->seek($rowKey + 1);
    if ($file->valid()) {
      $file->seek($rowKey);
    } else {
      var_dump($row);
      echo "<br>";
      $path = "file.2.txt";
    }
  }
  $whileCounter++;
}

如果您应用自定义 .csv 文件(至少有五个非空行)而不是 file.1.txt 和 file.2.txt,您将看到第二个和第三个输出是相同的(第二个和第三个输出是第一个和file.2.txt 的“第二”行)。这里有什么问题?

4

1 回答 1

2

那没有。Foreach 在您的$file变量上使用迭代器,即使您更改了$file.

或者,换句话说,foreach将继续查看 之前的内容$file,而不管您之后如何处理它。这是因为$file实际上不是SplFileObject,而是对它的引用,并且引用被foreach.

于 2015-08-16T09:45:31.540 回答