2009-08-04 41 views
11

Tôi đang sử dụng chức năng giải nén đơn giản (như được xem bên dưới) cho tệp của mình để tôi không phải giải nén tệp theo cách thủ công trước khi chúng được xử lý thêm.Mở gói các tệp lớn bằng gzip trong PHP

function uncompress($srcName, $dstName) { 
    $string = implode("", gzfile($srcName)); 
    $fp = fopen($dstName, "w"); 
    fwrite($fp, $string, strlen($string)); 
    fclose($fp); 
} 

Vấn đề là nếu tệp gzip lớn (ví dụ: 50mb) việc giải nén mất một lượng lớn ram để xử lý.

Câu hỏi: Tôi có thể phân tích cú pháp tệp đã được nén trong các đoạn và vẫn nhận được kết quả chính xác không? Hoặc có cách nào tốt hơn để xử lý vấn đề giải nén các tệp gzip lớn (ngay cả khi nó mất thêm vài giây nữa)?

Trả lời

41

gzfile() là một phương pháp tiện lợi gọi gzopen, gzread và gzclose.

Vì vậy, có, bạn có thể tự gzopen và gzread tệp theo khối.

này sẽ giải nén các tập tin trong khối 4KB:

function uncompress($srcName, $dstName) { 
    $sfp = gzopen($srcName, "rb"); 
    $fp = fopen($dstName, "w"); 

    while (!gzeof($sfp)) { 
     $string = gzread($sfp, 4096); 
     fwrite($fp, $string, strlen($string)); 
    } 
    gzclose($sfp); 
    fclose($fp); 
} 
+3

Ngọt ngào! Thử nghiệm trên một tệp gzip 1MB trích xuất tới 48MB - trước: Thời gian xử lý: 12,1447 giây, Sử dụng bộ nhớ tối đa: 96512kB - Giải pháp của bạn: Thời gian xử lý: 0,6705s, Sử dụng bộ nhớ đỉnh: 256kB Cảm ơn bạn :) – Lukas

+0

Bạn có thể có được hiệu suất tốt hơn bằng cách tinh chỉnh số ở cuối cuộc gọi gzread. Tôi đã không thử nó mặc dù. – Powerlord

+0

20 lần tốt hơn là đủ tốt, và sẽ vẫn đủ tốt trong một thời gian rất dài. Tôi sẽ phải rất tuyệt vọng hoặc sử dụng các tệp lớn để thử và chỉnh sửa điều này hơn nữa :) – Lukas

1

thử với

function uncompress($srcName, $dstName) { 
    $fp = fopen($dstName, "w"); 
    fwrite($fp, implode("", gzfile($srcName))); 
    fclose($fp); 
} 

tham số $ chiều dài là không bắt buộc.

+0

Dường như cách tiếp cận này không giống như cách tiếp cận ban đầu sử dụng một lượng bộ nhớ lớn. Toàn bộ tệp đang được đọc và được lưu trữ trong bộ nhớ. – Lukas

+0

không được tải vào tệp dữ liệu biến (tương tự như phát trực tuyến). không phải là một mô hình đối tượng khi tải chuỗi đối tượng. Ví dụ này không ảnh hưởng đến "php_value memory_limit". ví dụ của bạn ảnh hưởng đến biến này trong tệp "php.ini". –

1

Nếu bạn đang ở trên một máy chủ Linux, có privilegies cần thiết để chạy các lệnh và lệnh gzip được cài đặt, bạn có thể thử gọi nó với cái gì đó như shell_exec

một cái gì đó một chút như thế này, tôi đoán, sẽ do:

shell_exec('gzip -d your_file.gz'); 

Bằng cách này, tệp sẽ không được giải nén bằng PHP.


Là một sidenote:

  • chăm sóc Đưa những nơi mà các lệnh được chạy từ (ot sử dụng một Swith để nói "để giải nén để rằng thư mục")
  • Bạn có thể muốn có một cái nhìn tại escapeshellarg quá ;-)
+0

Cảm ơn bạn, tôi có quyền truy cập trình bao, nhưng vẫn chưa tìm hiểu cách sử dụng nó. – Lukas

0

Như maliayas đã đề cập, nó có thể dẫn đến một lỗi. Tôi đã trải qua một sự cố bất ngờ trong vòng lặp while, nhưng tệp gz đã được giải nén thành công. Toàn bộ mã trông giống như thế này và hoạt động tốt hơn cho tôi:

function gzDecompressFile($srcName, $dstName) { 
    $error = false; 

    if($file = gzopen($srcName, 'rb')) { // open gz file 

     $out_file = fopen($dstName, 'wb'); // open destination file 

     while (($string = gzread($file, 4096)) != '') { // read 4kb at a time 
      if(!fwrite($out_file, $string)) { // check if writing was successful 
       $error = true; 
      } 
     } 

     // close files 
     fclose($out_file); 
     gzclose($file);  

    } else { 
     $error = true; 
    } 

    if ($error) 
     return false; 
    else 
     return true; 
} 
Các vấn đề liên quan