У меня есть следующий код, который берет $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);
}

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

У меня вопрос, можно ли его оптимизировать и / или делаю ли я что-нибудь трагически неправильное?

Благодарность

1
pee2pee 5 Окт 2019 в 16:04

1 ответ

Лучший ответ

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

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

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);
    }
}
1
Nigel Ren 5 Окт 2019 в 14:02