PHP 不会将整个文件读入数组,只会读取部分文件

PHP won't read full file into array, only partial

我有一个包含 3,200,000 行 csv 数据(450 列)的文件。总文件大小为 6 GB。

我是这样读文件的:

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

毫无疑问,它只读取了 897,000 行。我用 'print_r' 和 echo sizeof($data) 确认。我将 "memory_limit" 增加到一个荒谬的值,如 80 GB,但没有任何影响。

现在,它确实读取了我的另一个大文件,行数相同 (3,200,000),但只有几列,因此文件总大小为 1.1 GB。所以这似乎是一个总文件大小问题。仅供参考,$data 数组中的 897,000 行大约为 1.68 GB。

更新:我将第二个(更长的)文件增加到 2.1 GB(超过 500 万行)并且它可以正常读取,但将另一个文件截断为 1.68 GB。所以看起来不是尺寸问题。如果我继续将第二个文件的大小增加到 2.2 GB,而不是截断它并继续执行程序(就像它对第一个文件所做的那样),它就会死掉并进行核心转储。

更新:我通过打印整数和浮点数验证我的系统是 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";

?>

此脚本的输出是:

整数(2147483647)

整数(2147483648)

整数(50000000000)

整数(9223372036854775807)

浮动(9.2233720368548E+18)

浮动(5.0E+19)

PHP_INT_MAX: 9223372036854775807

PHP_INT_SIZE:8 字节(64 位)

既然它是 64 位的,而且内存限制设置得非常高,为什么 PHP 不能读取大于 2.15 GB 的文件?

想到的一些事情:

  • 如果您使用的是 32 位 PHP,则无法读取大于 2GB 的文件。
  • 如果读取文件时间过长,可能会超时。
  • 如果文件很大,全部读入内存会出问题。通常最好读取数据块并对其进行处理,除非您需要随机访问文件的所有部分。
  • 另一种方法(我过去使用过)是将大文件分割成更小、更易于管理的文件(例如,如果它是一个简单的日志文件,应该可行)

我修好了。我所要做的就是改变我阅读文件的方式。为什么...我不知道。

只读取 6.0 GB 中的 2.15 GB 的旧代码:

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

读取完整 6.0 GB 的新代码:

$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 GB 接近我读到的 32 位限制。