2010-05-01 28 views
25

Ok, tôi đang tìm cách nhanh nhất có thể để đọc tất cả nội dung của tệp thông qua php với filepath trên máy chủ, các tệp này có thể rất lớn. Vì vậy, nó rất quan trọng là nó làm một READ ONLY cho nó càng nhanh càng tốt.Cách nhanh nhất có thể đọc nội dung của một tệp

Đọc nó từng dòng nhanh hơn đọc toàn bộ nội dung? Mặc dù, tôi nhớ đọc trên một số điều này, rằng đọc toàn bộ nội dung có thể tạo ra lỗi cho các tệp lớn. Điều này có đúng không?

+0

* (tham khảo) * http://www.ibm.com/developerworks/library/os-php-readfiles/ – Gordon

+1

Câu hỏi này hơi cũ, nhưng để tham khảo trong tương lai, tôi đã tìm thấy [trang web này] (http://www.raditha.com/wiki/Readfile_vs_include) một số thời gian trước đây. Nó đã đánh giá một số phương thức đọc PHP và kết luận 'readfile()' và 'fpassthru' là nhanh nhất, miễn là bạn không cần xử lý tệp đó (nghĩa là không có tập lệnh PHP bên trong tệp cần xử lý). – jmbertucci

+0

Dưới đây là một số phương pháp PHP quan trọng để lấy nội dung và kiểm tra chúng bằng 'echo microtime' trước khi bắt đầu hàm, và sau khi hàm lặp lại' echo microtime' và xem kết quả: http://stackoverflow.com/questions/2176180/get -content-from-a-url-using-php –

Trả lời

33

Nếu bạn muốn tải các nội dung đầy đủ của một tập tin vào một biến PHP, dễ (và, có lẽ nhanh nhất) cách là file_get_contents. Tuy nhiên, nếu bạn đang làm việc với các tệp lớn, tải toàn bộ tệp vào bộ nhớ có thể không phải là một ý tưởng hay: có thể bạn sẽ gặp phải lỗi memory_limit vì PHP sẽ không cho phép tập lệnh của bạn sử dụng nhiều hơn (thường) một vài bộ nhớ mega-byte.


Vì vậy, ngay cả khi nó không phải là giải pháp nhanh nhất, đọc dòng tập tin bằng dòng (fopen + fgets + fclose), và làm việc với những dòng khi đang bay, mà không cần tải toàn bộ tập tin vào bộ nhớ, có thể cần thiết ...

+0

Có sử dụng 'SESSIONS' để lưu trữ thông tin này hay không, vì vậy chúng tôi không phải tiếp tục mở tệp nếu nó đã được mở một lần? – SoLoGHoST

+3

Trước hết, phiên là * (theo mặc định) * được lưu trữ trong các tệp ;;; sau đó, bạn không nên đặt dữ liệu lớn vào phiên * (vì nó được tuần tự hóa/unserialized cho mỗi yêu cầu) * ;;; và lưu trữ dữ liệu này thành phiên sẽ sao chép dữ liệu: mỗi người dùng có một phiên khác nhau ;;; Vì vậy, tôi sẽ nói rằng không, lưu trữ này để phiên không phải là một ý tưởng tốt. –

+1

Vì vậy, xin lỗi, nếu tôi không hiểu điều này, bạn có nghĩ tốt hơn là lưu nó dưới dạng chuỗi được tuần tự hóa vào cơ sở dữ liệu sau khi đọc (các) tệp theo dòng và không chỉ mở nó bằng cách unserializing nó? – SoLoGHoST

5

Bạn có thể sử dụng file_get_contents

Ví dụ:

$homepage = file_get_contents('http://www.example.com/'); 
echo $homepage; 
+0

Vì vậy, điều này sẽ làm việc cho bất kỳ tập tin kích thước? Không có vấn đề lớn như thế nào trong các tập tin? – SoLoGHoST

+0

@SoLoGHoST: không có giới hạn bộ nhớ. – Sarfraz

+0

Ồ, ok, hơn thế này không phải là điều tôi muốn. Dù sao cũng cảm ơn. – SoLoGHoST

0

Đọc toàn bộ tệp trong một lần nhanh hơn.

Nhưng các tệp lớn có thể ăn hết bộ nhớ của bạn và gây ra sự cố. Sau đó, đặt cược an toàn nhất của bạn là đọc từng dòng một.

8
$file_handle = fopen("myfile", "r"); 
while (!feof($file_handle)) { 
    $line = fgets($file_handle); 
    echo $line; 
} 
fclose($file_handle); 
  1. Mở tập tin và lưu trữ trong $file_handle như tham chiếu đến tập tin đó.
  2. Kiểm tra xem bạn đã ở cuối tệp chưa.
  3. Tiếp tục đọc tệp cho đến khi bạn kết thúc, in từng dòng khi bạn đọc.
  4. Đóng tệp.
+0

Đọc một dòng tại một thời điểm có thể không tối ưu nếu tệp có các dòng rất ngắn. Đọc theo khối của một kích thước cụ thể có thể thực hiện tốt hơn – GordonM

14

file_get_contents() là cách tối ưu nhất để đọc các file trong PHP, tuy nhiên - kể từ khi bạn đang đọc tập tin trong bộ nhớ bạn luôn giới hạn dung lượng bộ nhớ có sẵn.

Bạn có thể phát hành ini_set('memory_limit', -1) nếu bạn có quyền phù hợp nhưng bạn vẫn bị giới hạn bởi dung lượng bộ nhớ khả dụng trên hệ thống của mình, điều này là phổ biến đối với tất cả ngôn ngữ lập trình.

Giải pháp duy nhất là để đọc các tập tin trong khối, cho rằng bạn có thể sử dụng file_get_contents() với các đối số thứ tư và thứ năm ($offset$maxlen - quy định tại byte):

string file_get_contents(string $filename[, bool $use_include_path = false[, resource $context[, int $offset = -1[, int $maxlen = -1]]]]) 

Đây là một ví dụ mà tôi sử dụng kỹ thuật này để phục vụ các tệp tải xuống lớn:

public function Download($path, $speed = null) 
{ 
    if (is_file($path) === true) 
    { 
     set_time_limit(0); 

     while (ob_get_level() > 0) 
     { 
      ob_end_clean(); 
     } 

     $size = sprintf('%u', filesize($path)); 
     $speed = (is_int($speed) === true) ? $size : intval($speed) * 1024; 

     header('Expires: 0'); 
     header('Pragma: public'); 
     header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
     header('Content-Type: application/octet-stream'); 
     header('Content-Length: ' . $size); 
     header('Content-Disposition: attachment; filename="' . basename($path) . '"'); 
     header('Content-Transfer-Encoding: binary'); 

     for ($i = 0; $i <= $size; $i = $i + $speed) 
     { 
      ph()->HTTP->Flush(file_get_contents($path, false, null, $i, $speed)); 
      ph()->HTTP->Sleep(1); 
     } 

     exit(); 
    } 

    return false; 
} 

Một tùy chọn khác là sử dụng các les s tối ưu hóa fopen(), feof(), fgets()fclose() chức năng, đặc biệt nếu bạn quan tâm về việc toàn bộ dây chuyền cùng một lúc, đây là another example I provided in another StackOverflow question for importing large SQL queries into the database:

function SplitSQL($file, $delimiter = ';') 
{ 
    set_time_limit(0); 

    if (is_file($file) === true) 
    { 
     $file = fopen($file, 'r'); 

     if (is_resource($file) === true) 
     { 
      $query = array(); 

      while (feof($file) === false) 
      { 
       $query[] = fgets($file); 

       if (preg_match('~' . preg_quote($delimiter, '~') . '\s*$~iS', end($query)) === 1) 
       { 
        $query = trim(implode('', $query)); 

        if (mysql_query($query) === false) 
        { 
         echo '<h3>ERROR: ' . $query . '</h3>' . "\n"; 
        } 

        else 
        { 
         echo '<h3>SUCCESS: ' . $query . '</h3>' . "\n"; 
        } 

        while (ob_get_level() > 0) 
        { 
         ob_end_flush(); 
        } 

        flush(); 
       } 

       if (is_string($query) === true) 
       { 
        $query = array(); 
       } 
      } 

      return fclose($file); 
     } 
    } 

    return false; 
} 

Những kỹ thuật mà bạn sử dụng thực sự sẽ phụ thuộc vào những gì bạn đang cố gắng làm (như bạn có thể thấy với hàm nhập khẩu SQL và hàm tải xuống), nhưng bạn sẽ luôn phải đọc dữ liệu theo các khối.

0

Nếu bạn không lo lắng về bộ nhớ và kích thước tập tin,

$lines = file($path); 

$ dòng sau đó là hàng loạt các tập tin.

+0

mà tôi tin rằng chỉ là một preg_split (/ \ r? \ N? /, File_get_contents()) – ppostma1

-2

Bạn có thể dùng thử cURL (http://php.net/manual/en/book.curl.php).

Altho bạn có thể muốn kiểm tra, nó có giới hạn của nó Như Vâng

$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL, "http://example.com/"); 
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); 
$data = curl_exec ($ch); // Whole Page As String 
curl_close ($ch); 
+2

Bất kỳ lý do nào để viết hoa chữ cái đầu tiên của mỗi từ? – developerbmw

1
foreach (new SplFileObject($filepath) as $lineNumber => $lineContent) { 

    echo $lineNumber."==>".$lineContent; 
    //process your operations here 
} 
Các vấn đề liên quan