PHP: Как оптимизировать цикл через CSV и запись строки в файл, зависящий от значения в столбце - PullRequest
1 голос
/ 05 октября 2019

У меня есть следующий код, который принимает $filename и проходит через него. Если 9-й столбец находится в массиве значений (здесь не показан), я его игнорирую.

В противном случае я записываю строку в файл, имя которого основано на 3-м столбце.

if (($handle = fopen($filename, "r")) !== FALSE) {
    fgetcsv($handle);
    while (($line = fgetcsv($handle, 2000, ";")) !== FALSE) {
        if (!in_array($line[8], $exclude)) {
            $d = str_replace('/','',$line[2]);
            $f = fopen($base.$d.'.csv', "a");
            fputcsv($f, $line);
            fclose($f);
            unset($line);
        }
    }
    fclose($handle);
}

Это отлично работает. Однако это очень медленно. У меня есть 200Mb CSV, через который он проходит.

Мой вопрос: можно ли его оптимизировать и / или я делаю что-то трагически неправильно?

Спасибо

1 Ответ

1 голос
/ 05 октября 2019

Открытие и закрытие файлов всегда является дорогостоящей операцией, поэтому уменьшение этого поможет, когда вы открываете и закрываете файл для каждой строки во входном файле.

Этот код сохраняет массив открытых файлов и каждый из них. время проверяет, открыт ли он, если это так, просто используйте сохраненный дескриптор, если не открыт, и сохраните новый дескриптор. Затем в конце кода он просматривает все открытые файлы и закрывает их все ...

if (($handle = fopen($filename, "r")) !== FALSE) {
    $outHandles = [];
    fgetcsv($handle);
    while (($line = fgetcsv($handle, 2000, ";")) !== FALSE) {
        if (!in_array($line[8], $exclude)) {
            $d = str_replace('/','',$line[2]);
            if ( isset($outHandles[$d]) )   {
                $f = $outHandles[$d];
            }
            else    {
                $f = fopen($base.$d.'.csv', "a");
                $outHandles[$d] = $f;
            }
            fputcsv($f, $line);
            unset($line);
        }
    }
    fclose($handle);
    foreach ( $outHandles as $file )    {
        fclose($file);
    }
}
...