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) が 1 つだけ存在する必要があります。したがって、 foreach ループ内のどこかに、これを処理する if ステートメントがあります。

すべてのファイルは同じ構造を持っているため、問題が発生します。次のファイルを読み取るために新しい foreach を作成したくありません-私が書いたように、まったく必要ないかもしれないので、新しい foreach を作成する代わりに既存の foreach を使用したいと思います。$file 変数を他のファイルの内容で上書きし、foreach または他のループを 1 つだけ使用して反復する可能性はありますか? 例えば:

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) を呼び出して前の行に移動すると、次のファイルは最初の行を 2 回出力し、2 番目の行は見落とされます。3行目以降はきれいに印刷されています。これは、以下のコードで達成される問題です。

$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++;
}

file.1.txt と file.2.txt の代わりにカスタム .csv ファイル (少なくとも 5 つの空でない行を含む) を適用すると、2 番目と 3 番目の出力が同じであることがわかります (2 番目と 3 番目の出力は最初とfile.2.txt の「2」行目)。ここで何が問題なのですか?

4

1 に答える 1

2

存在しない。Foreach は$file変数に対してイテレータを使用し、 の値を変更してもそのイテレータは引き続き有効です$file

または、別の言い方をすれば、後で何をするかに関係なく、foreachの前の内容を見続けます。$fileこれは、$fileが実際にはSplFileObjectではなく、それへの参照であり、参照が によって使用されているためforeachです。

于 2015-08-16T09:45:31.540 に答える