2012-12-08 102 views
0

是否有一些PHP函數或類允許我像字符數組一樣讀取文件?PHP中的隨機訪問文件

例如:

$string = str_split('blabla'); 

$i = 0; 

switch($string[$i]){ 

    case 'x': 
    do_something(); 
    $i++; 


    case 'y': 
    if(isset($string[++$i])) 
     do_something_else(); 
    else 
     break; 

    case 'z': 
     // recursive call of this code etc.. 

} 

我知道,我可以使用$string = file_get_contents($file),但問題是,我得到用於微小800K的文件(如80MB)的內存量巨大。

所以,我可以以某種方式「流」在我的代碼上面的文件與某種類型的數組訪問,如類我會調用isset()時自動從文件讀取數據? :)

+0

不,它不是真正的隨機。我將只向前移動$ i ... – Alex

回答

5

您可以使用fseekfgetc在文件中跳轉並一次讀取單個字符。

// Leaves the file handle modified 
function get_char($file, $char) { 
    fseek($file, $char); 
    return fgetc($file); 
} 

你提到你想要的數組行爲具體。你可以建立一個類來實現ArrayAccess來支持這個。

這可能有幾個原因是危險的:

  • 你需要警惕$char輸入,請求指數過去文件
  • 文件句柄將不斷突變的長度(應該沒問題,只要你不使用它在其他地方)
  • 這可能是低效的(通過緩存過去請求偏移)

稍微更有效的替代方法是「懶惰」地讀取文件(即,一次讀取它,而不是一次讀取)。這裏有一些(未經測試)代碼:

class BufferedReader { 
    // The size of a chunk in bytes 
    const BUFFER_SIZE = 512; 

    protected $file; 
    protected $data; 

    function __construct($fname) { 
     $this->file = fopen($fname, 'r'); 
    } 

    function read_buffer() { 
     $this->data .= fread($this->file, self::BUFFER_SIZE); 
    } 

    function get_char($char) { 
     while ($char >= strlen($this->data) && !feof($this->file)) { 
      $this->read_buffer(); 
     } 

     if ($char >= strlen($this->data)) { 
      return FALSE; 
     } 

     return substr($this->data, $char, 1); 
    } 
} 
+1

還有字符編碼需要擔心。你可以跳到一個多字節glpyh的中間點,這將是非常令人沮喪的線... – Charles

+0

謝謝,我設法做到這一切後,所有與fgetc(我不需要fseek),內存使用情況是正常的,但與file_get_contents相比似乎非常慢,比慢5倍(約1.5秒)慢。這個函數實際上是通過char來讀取char文件嗎?如果是這樣,是不是有類似的功能,像8K的緩衝區中讀取文件?我的意思是表現得像fgetc,但更有效地讀取文件 – Alex

+0

@Alex如果你想讀緩衝區,使用['fread'](http://php.net/fread)並指定你想要的數據長度讀。逐字讀取將比讀取緩衝區慢,然後逐個處理緩衝區,直到讀取完所有數據。 – drew010