file — SplFileObject — Неверный вывод для второй строки при использовании метода seek ()

Перейдите к ОБНОВЛЕНИЕ, чтобы прочитать, что является актуальной проблемой сейчас. Старый вопрос уже был решен с первым ответом, представленным Бертом Питерсом.

СТАРЫЙ ВОПРОС:
У меня есть несколько файлов с именами 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 (), потому что я хотел бы принять решение относительно некоторой информации, которая добавляется к каждой следующей строке. Поэтому, если я использую поиск ($ rowKey + 1), который помогает мне получить данные следующей строки (я использую $ file-> current () при изменении строки), и после этого я вызываю поиск ($ 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, вы увидите, что второй и третий выходные данные одинаковы (второй и третий выходные данные являются первыми и «вторые» строки файла.2.txt). Что здесь может быть не так?

1

Решение

Нет. Foreach использует итератор над вашим $file переменная, и этот итератор остается действительным, даже если вы изменили значение $file,

Или, чтобы выразить это по-другому, foreach продолжит смотреть на предыдущее содержание $fileнезависимо от того, что вы делаете с ним потом. Это потому что $file на самом деле не SplFileObject, а скорее ссылка на него, а ссылка используется foreach,

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]