Чтения очень больших файлов в PHP

fopen не удается, когда я пытаюсь прочитать в файле очень среднего размера в PHP. A 6 meg file делает его душить, хотя мелкие файлы 100k это просто прекрасно. я читал, что иногда необходимо перекомпилировать PHP С -D_FILE_OFFSET_BITS=64 флаг для того, чтобы читать файлы более 20 гигабайт или что-то смешное, но не должно ли у меня быть никаких проблем с файлом 6 meg? В конце концов, мы захотим прочитать файлы, которые составляют около 100 мегабайт, и было бы неплохо открыть их, а затем прочитать через них строка за строкой с fgets, как я могу сделать с меньшими файлами.

каковы ваши трюки / решения для чтения и выполнения операций с очень большими файлами в PHP?

Update: вот пример простого codeblock, который терпит неудачу в моем файле 6 meg-PHP, похоже, не выдает ошибку, он просто возвращает false. Может, я делаю что-то очень глупое?

$rawfile = "mediumfile.csv";

if($file = fopen($rawfile, "r")){  
  fclose($file);
} else {
  echo "fail!";
}

еще одно обновление: спасибо всем за вашу помощь, это оказалось чем-то невероятно тупой-проблема с разрешениями. Мой маленький файл необъяснимо имел разрешения на чтение, когда большой файл этого не делал. До!

8 ответов


вы уверены, что это fopen это сбой, а не настройка тайм-аута вашего скрипта? Значение по умолчанию обычно составляет около 30 секунд или около того, и если ваш файл занимает больше времени для чтения, это может сработать.

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

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

$handle = fopen("/tmp/uploadfile.txt", "r") or die("Couldn't get handle");
if ($handle) {
    while (!feof($handle)) {
        $buffer = fgets($handle, 4096);
        // Process buffer here..
    }
    fclose($handle);
}

редактировать

PHP, похоже, не выдает ошибку, он просто возвращает false.

- это путь к $rawfile правильно относительно того, где работает скрипт? Возможно, попробуйте установить абсолютный путь для имени файла.


сделал 2 теста с файлом 1.3 GB и файлом 9.5 GB.

1.3 ГБ

используя fopen()

этот процесс использовал 15555 мс для своих вычислений.

он провел 169 МС в системных вызовах.

используя file()

этот процесс использовал 6983 мс для своих вычислений.

он провел 4469 МС в системных вызовах.

9.5 ГБ

используя fopen()

этот процесс использовал 113559 мс для своих вычислений.

он провел 2532 МС в системных вызовах.

используя file()

этот процесс использовал 8221 мс для своих вычислений.

он провел 7998 МС в системных вызовах.

кажется file() быстрее.


Я использовал fopen для открытия видеофайлов для потоковой передачи, используя PHP-скрипт в качестве сервера потоковой передачи видео, и у меня не было проблем с файлами размером более 50/60 МБ.


Ну, вы можете попробовать использовать функцию readfile, если вы просто хотите вывести файл.

Если это не так - может быть, вы должны думать о дизайне приложения, почему вы хотите открывать такие большие файлы на веб-запросы?


Если проблема вызвана ограничением памяти, вы можете попробовать установить его более высокое значение (это может работать или нет в зависимости от конфигурации php).

это устанавливает ограничение памяти до 12 Мб

ini\_set("memory_limit","12M");

для меня fopen() очень медленно с файлами более 1 Мб, file() гораздо быстрее.

просто пытаюсь читать строки по 100 за раз и создавать пакетные вставки,fopen() занимает 37 секунд против file() занимает 4 секунды. Должно быть string->array шаг построен в file()

Я бы попробовал все параметры обработки файлов, чтобы увидеть, что будет работать лучше всего в вашем приложении.


Не уверен, что вы решили проблему. Я также пытался обработать большой файл, а наткнулся на веб-сайт, который я думаю, может быть ответом.

использование команды yield.

https://www.sitepoint.com/performant-reading-big-files-php/