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

时间:2019-01-03 00:16:04

标签: php arrays csv coredump

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

我这样读取文件:

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

没有失败,它仅读取897,000行。我用'print_r'和echo sizeof($data)确认。我将“ memory_limit”增加到一个可笑的值,例如80 GB,但没有任何改变。

现在,它DID读取了我的另一个大文件,行数相同(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";

?>

此脚本的输出为:

int(2147483647)

int(2147483648)

int(50000000000)

int(9223372036854775807)

float(9.2233720368548E + 18)

浮动(5.0E + 19)

PHP_INT_MAX:9223372036854775807

PHP_INT_SIZE:8个字节(64位)

因此,由于它是64位,并且内存限制设置得很高,因此PHP为什么不读取大于2.15 GB的文件?

2 个答案:

答案 0 :(得分:3)

想到的一些事情

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

答案 1 :(得分:0)

我修复了它。我要做的就是更改读取文件的方式。为什么...我不知道。

在6.0 GB中仅读取2.15 GB的旧代码:

LEFT()

读取完整的6.0 GB的新代码:

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

请随时阐明原因。使用

时必须有一些限制
$data = array();

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

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

有趣的是,2.15 GB接近我读到的32位限制。