2008-10-02 73 views
19

fopen không thành công khi tôi cố gắng đọc trong một tệp có kích thước rất vừa phải trong PHP. A 6 meg file làm cho nó bị nghẹt thở, mặc dù các tệp nhỏ hơn xung quanh 100k vẫn ổn. Tôi đã đọc rằng đôi khi cần phải biên dịch lại PHP với cờ -D_FILE_OFFSET_BITS=64 để đọc các tệp trên 20 hợp đồng biểu diễn hoặc điều gì đó vô lý, nhưng tôi không nên gặp vấn đề với tệp 6 meg? Cuối cùng, chúng tôi sẽ muốn đọc trong các tệp có dung lượng khoảng 100 megabyte, và sẽ tốt hơn nếu có thể mở chúng và sau đó đọc qua chúng theo từng dòng với các fgets như tôi có thể làm với các tệp nhỏ hơn.Đọc các tệp rất lớn trong PHP

gì là thủ đoạn của bạn/giải pháp cho việc đọc và làm các hoạt động trên các tập tin rất lớn trong PHP?

Cập nhật: Dưới đây là một ví dụ về một codeblock đơn giản mà không thành công trên tập 6 meg của tôi - PHP dường như không ném ra một lỗi, nó chỉ trả về false. Có lẽ tôi đang làm một cái gì đó cực kỳ ngu ngốc?

$rawfile = "mediumfile.csv"; 

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

Cập nhật khác: Cảm ơn sự giúp đỡ của bạn, nó đã trở thành một điều cực kỳ ngu ngốc - vấn đề quyền. Tập tin nhỏ của tôi không hiểu sao có quyền đọc khi tệp lớn hơn không. Doh!

+0

Bạn chỉ cần cố gắng để vượt qua các tập tin qua? I E. Tải về? Hoặc bạn có thực sự phân tích dữ liệu trong các tệp cho một số mục đích không? Cám ơn. – DreamWerx

+0

nó không nên thất bại mà không tạo ra một cảnh báo/lỗi. Vui lòng tắt tất cả các lỗi bằng error_reporting (E_ALL) và đảm bảo display_errors được đặt thành bật để hiển thị trong trình duyệt của bạn hoặc kiểm tra nhật ký lỗi máy chủ web của bạn. –

Trả lời

36

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 kịch bản của bạn - đọc các tập tin vào một mảng có thể đi qua này, vì vậy kiểm tra log lỗi của bạn để 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.

+3

Nó chỉ là giải pháp có thể làm thế nào để mở các tập tin thực sự lớn. Tôi đang xử lý bởi giải pháp này tập tin 1.5GB mà không có bất kỳ vấn đề. Tất cả các giải pháp khác như file_get_contents của tập tin sẽ đọc toàn bộ tập tin vào bộ nhớ. Cách tiếp cận này là xử lý từng dòng một. – StanleyD

+0

Tại sao 4096 có nghĩa là một dòng? – Phoenix

+0

@Phoenix 4096 có nghĩa là đọc tối đa 4096 - 1 byte mà không gặp phải ngắt dòng. Kiểm tra hướng dẫn. – a3f

0

Bạn cũng có thể thử sử dụng hàm readfile nếu bạn chỉ muốn xuất tệp.

Nếu đây không phải là trường hợp - có lẽ bạn nên suy nghĩ về việc thiết kế của ứng dụng, tại sao bạn muốn để mở các file lớn như vậy trên các yêu cầu web?

+0

Chúng tôi phải tự động thêm các tập dữ liệu lớn, do đó, các tệp CSV lớn có thể được người dùng tải lên và được phân tích và tích hợp vào cơ sở dữ liệu của ứng dụng. Tôi rất thích các đề xuất khác để tiếp cận nếu bạn nghĩ rằng đọc và phân tích các tệp được tải lên bằng PHP không phải là cách tốt nhất để đi. –

+0

Tôi sẽ không nghĩ rằng PHP sẽ có một vấn đề với các tập tin csv 6MB? Có vẻ như một tệp nhỏ đủ để xử lý. Theo nhận xét ở trên, vui lòng đăng lỗi/và mã chính xác. Có thể là lỗi bộ nhớ của bạn đánh? Hoặc max_execution_time? Chúng tôi cần thêm thông tin để trợ giúp. – DreamWerx

1

tôi đã sử dụng fopen để mở file video cho streaming, sử dụng một kịch bản php như một video streaming máy chủ, và tôi đã không có vấn đề với các tập tin kích thước hơn 50/60 MB.

0

Nếu sự cố xảy ra do đạt đến giới hạn bộ nhớ, bạn có thể thử đặt giá trị cao hơn (điều này có thể hoạt động hoặc không phụ thuộc vào cấu hình của php).

này đặt ra giới hạn bộ nhớ đến 12 Mb

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

Lưu ý: Mặc dù điều này có thể hữu ích, nhưng nó chỉ trì hoãn sự cố: khi tệp 15 MB xuất hiện trong, vấn đề trở lại. (Nếu tệp của bạn sẽ không bao giờ vượt quá giới hạn nhất định, điều này có thể khiến cho sự cố không còn nữa.) – Piskvor

0

đối với tôi, fopen() đã được rất chậm với các file trên 1mb, tập tin() là nhanh hơn nhiều. Chỉ cần cố gắng đọc các dòng 100 tại một thời điểm và tạo ra chèn hàng loạt, fopen() mất 37 giây so với tệp() mất 4 giây. Phải là chuỗi string-> array được tích hợp vào tệp()

Tôi sẽ thử tất cả các tùy chọn xử lý tệp để xem tùy chọn nào sẽ hoạt động tốt nhất trong ứng dụng của bạn.

5

Đã 2 bài kiểm tra với một file 1,3GB và 9.5GF file

1,3

Sử dụng fopen()

Quá trình này sử dụng 15.555 ms cho tính toán của mình.

Nó dành 169 ms trong hệ thống gọi

Sử dụng file()

Quá trình này sử dụng 6983 ms cho tính toán của mình.

Nó dành 4469 ms trong hệ thống gọi

9.5GB

Sử dụng fopen()

Quá trình này sử dụng 113.559 ms cho tính toán của nó

Nó dành 2.532 ms trong hệ thống gọi

Sử dụng file()

Quá trình này sử dụng 8221 ms cho tính toán của nó

Nó dành 7998 ms trong hệ thống gọi

vẻ file() nhanh

Các vấn đề liên quan