2013-02-13 17 views
7

Tôi đang cố gắng phân tích cú pháp tệp được phân tách bằng tab có kích thước ~ 1GB.Đọc và phân tích nội dung của tệp rất lớn

đâu tôi chạy kịch bản tôi nhận được:

Fatal error: Allowed memory size of 1895825408 bytes exhausted (tried to allocate 1029206974 bytes) ... 

Kịch bản của tôi vào lúc này là chỉ cần:

$file = file_get_contents('allCountries.txt') ; 

$file = str_replace(array("\r\n", "\t"), array("[NEW*LINE]", "[tAbul*Ator]"), $file) ; 

tôi đã thiết lập các giới hạn bộ nhớ trong php.ini là -1, sau đó cung cấp cho tôi:

Fatal error: Out of memory (allocated 1029963776) (tried to allocate 1029206974 bytes) 

Vẫn còn một phần để mở tệp và sau đó chuyển sang phần tiếp theo để ít bộ nhớ hơn được sử dụng hết cùng một lúc?

+1

Tại sao không xử lý dòng tệp theo dòng ?! –

Trả lời

10

Vâng, bạn có thể đọc từng dòng một:

$handle = @fopen("/tmp/inputfile.txt", "r"); 
if ($handle) { 
    while (($buffer = fgets($handle, 4096)) !== false) { 
     echo $buffer; 
    } 
    fclose($handle); 
} 
+1

Đối với một tệp được phân tách bằng tab, hãy sử dụng fgetcsv() để đơn giản –

1

Bạn có chắc chắn rằng đó là fopen đó là thất bại và không thiết lập thời gian chờ tập lệnh của bạn? Mặc định thường là khoảng 30 giây hoặc lâu hơn và nếu tệp của bạn mất nhiều thời gian hơn để đọc, nó có thể bị vấp ngã.

Một điều cần xem xét có thể là giới hạn bộ nhớ trên tập lệnh của bạn - đọc tệp vào một mảng có thể đi qua này, vì vậy hãy kiểm tra nhật ký lỗi của bạn để biết cảnh báo bộ nhớ.

Nếu không có vấn đề nào ở trên, bạn có thể xem xét sử dụng fgets để đọc tệp theo từng dòng, xử lý khi bạn thực hiện.

$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); 
} 

Sửa

PHP dường như không ném ra một lỗi, nó chỉ trả về false.

Đường dẫn đến $rawfile có đúng so với vị trí tập lệnh đang chạy không? Có lẽ thử đặt một đường dẫn tuyệt đối ở đây cho tên tệp.

+0

Nếu tôi chỉ tải tệp vào bộ nhớ nó xảy ra trong khoảng 2 giây, lỗi xảy ra với str_replace nhưng tôi sẽ thử đề xuất theo dòng. – imperium2335

+0

lỗi xảy ra với str_replace vì trong trường hợp này, php cố gắng sao chép cùng kích thước bộ nhớ vào một biến khác –

2

Bạn phải sử dụng các khối để đọc tệp. Kiểm tra câu trả lời của câu hỏi này. https://stackoverflow.com/a/6564818/1572528

Bạn cũng có thể thử sử dụng tính năng này cho các tệp nhỏ hơn.

ini_set('memory_limit', '32M'); //max size 32m 
1

Có, sử dụng fopen và fread/fgets cho việc này:

http://www.php.net/manual/en/function.fread.php

string fread (resource $handle , int $length) 

Set $ ​​dài đến bao nhiêu trong số các tập tin bạn muốn đọc. Trình xử lý $ lưu vị trí cho lần đọc mới, sau đó, với fseek bạn cũng có thể đặt vị trí sau ....