PHP не читает полный файл в массив, только частичный

У меня есть файл с 3200000 строк данных CSV (с 450 столбцами). Общий размер файла составляет 6 ГБ.

Я читаю файл так:

$data = file('csv.out');

В обязательном порядке он читает только 897 000 строк. Я подтвердил «print_r», и echo sizeof($data), Я увеличил «memory_limit» до смешного значения, например, 80 ГБ, но ничего не изменило.

Теперь он прочитал в моем другом большом файле то же самое количество строк (3 200 000), но только несколько столбцов, поэтому общий размер файла 1,1 ГБ. Так что, похоже, проблема с общим размером файла. К вашему сведению, 897 000 строк в массиве $ data составляют около 1,68 ГБ.

Обновление: я увеличил второй (более длинный) файл до 2,1 ГБ (более 5 миллионов строк), и он хорошо читает его, но обрезает другой файл до 1,68 ГБ. Так что, похоже, проблема не в размере. Если я продолжу увеличивать размер второго файла до 2,2 ГБ, вместо того, чтобы обрезать его и продолжить программу (как это происходит для первого файла), он умирает и выдает дампы ядра.

Обновление: я подтвердил, что моя система является 64-битной, печатая целые числа и числа с плавающей запятой:

<?php
$large_number = 2147483647;
var_dump($large_number);                     // int(2147483647)

$large_number = 2147483648;
var_dump($large_number);                     // float(2147483648)

$million = 1000000;
$large_number =  50000 * $million;
var_dump($large_number);                     // float(50000000000)

$large_number = 9223372036854775807;
var_dump($large_number);                     //
int(9223372036854775807)

$large_number = 9223372036854775808;
var_dump($large_number);                     //
float(9.2233720368548E+18)

$million = 1000000;
$large_number =  50000000000000 * $million;
var_dump($large_number);                     // float(5.0E+19)

print "PHP_INT_MAX: " . PHP_INT_MAX . "\n";
print "PHP_INT_SIZE: " . PHP_INT_SIZE . " bytes (" . (PHP_INT_SIZE * 8)     . "     bits)\n";

?>

Вывод этого скрипта:

INT (2147483647)

INT (2147483648)

INT (50000000000)

Int (9223372036854775807)

Поплавок (9.2233720368548E + 18)

Поплавок (5.0E + 19)

PHP_INT_MAX: 9223372036854775807

PHP_INT_SIZE: 8 байтов (64 бита)

Так как он 64-битный, а ограничение памяти установлено очень высоким, почему PHP не читает файлы> 2,15 ГБ?

0

Решение

Некоторые вещи, которые приходят на ум:

  • Если вы используете 32-битный PHP, вы не можете читать файлы размером более 2 ГБ.
  • Если чтение файла занимает слишком много времени, возможны тайм-ауты.
  • Если файл действительно огромен, то его чтение в память будет проблематичным. Обычно лучше читать блоки данных и обрабатывать их, если вам не нужен произвольный доступ ко всем частям файла.
  • Другой подход (который я использовал в прошлом) — это нарезать большой файл на более мелкие, более управляемые (например, должен работать, если это простой файл журнала)
3

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

Я починил это. Все, что мне нужно было сделать, это изменить способ чтения файлов. Почему я не знаю.

Старый код, который читает только 2,15 ГБ из 6,0 ГБ:

$data = file('csv.out');

Новый код, который читает полные 6,0 ГБ:

$data = array();

$i=1;
$handle = fopen('csv.out');

if ($handle) {
while (($data[$i] = fgets($handle)) !== false){
// process the line read
$i++;
}

Не стесняйтесь пролить свет на то, почему. Там должно быть некоторое ограничение при использовании

$var=file();

Интересно, что 2,15 ГБ близко к 32-битному пределу, о котором я читал.

0