2010-09-08 71 views
0

我有兩個文件,文件大約5MB,文件b大約66 MB。我需要找出是否有任何文件a中的行出現在文件b中,如果是,則將它們寫入文件c。stristr和速度

這是我目前處理它的方式:

ini_set("memory_limit","1000M"); 
set_time_limit(0); 
$small_list=file("a.csv"); 
$big_list=file_get_contents("b.csv"); 
$new_list="c.csv"; 
$fh = fopen($new_list, 'a'); 
foreach($small_list as $one_line) 
{ 
if(stristr($big_list, $one_line) != FALSE) 
    { 
    fwrite($fh, $one_line); 
    echo "record found: " . $one_line ."<br>"; 
    } 
} 

的問題是它的運行方式(成功)了一個多小時和它也許3000線成較小的文件160,000。有任何想法嗎?

回答

0

與哈希作爲指數構建陣列:在b_hash[md5($line)] = true

讀取文件a.csv線由a_hash[md5($line)] = array($offset, $length) 讀線,並存儲在文件b.csv逐行和存儲通過使用哈希作爲您將自動關閉的索引不會出現重複條目​​。

然後對於在文件內容中使用a_hash和b_hash中的索引讀取的每個散列(使用存儲在a_hash中的偏移量和長度)來提取實際的行文本。如果你對散列碰撞有偏執,那麼存儲b_hash的偏移/長度,並用stristr進行驗證。

這樣會運行得更快,並且使用起來遠遠遠遠不如FAR更少的內存。

如果你想減少內存的需求進一步並且不介意重複檢查,那麼:在a_hash[md5($line)] = false
逐行讀取和存儲

讀取文件a.csv行文件由行b.csv線,哈希行和檢查是否存在於a_hash中。
如果a_hash[md5($line)] == falsec.csv並設置a_hash[md5($line)] = true

對於第二個建議,一些示例代碼:

$a_file = fopen('a.csv','r'); 
$b_file = fopen('b.csv','r'); 
$c_file = fopen('c.csv','w+'); 

if(!$a_file || !$b_file || !$c_file) { 
    echo "Broken!<br>"; 
    exit; 
} 

$a_hash = array(); 

while(!feof($a_file)) { 
    $a_hash[md5(fgets($a_file))] = false; 
} 
fclose($a_file); 

while(!feof($b_file)) { 
    $line = fgets($b_file); 
    $hash = md5($line); 
    if(isset($a_hash[$hash]) && !$a_hash[$hash]) { 
     echo 'record found: ' . $line . '<br>'; 
     fwrite($c_file, $line); 
     $a_hash[$hash] = true; 
    } 
} 

fclose($b_file); 
fclose($c_file); 
+0

這有點高於我的頭,你知道一個很好的資源,我可以學習如何正確地做到這一點? – Mike 2010-09-08 05:09:13

+0

爲您添加了一個示例。似乎工作正常,但我還沒有完全進行廣泛的調試。應該足以讓你看到發生了什麼事情,並且與原來相比,它將在少量空間中運行。 – Mike 2010-09-08 05:37:03

+0

哇,它設法在45秒內完成整個65mb文件...非常感謝,你真的爲我節省了一個非常非常深的夜晚。另外自動地是我最喜歡的詞。 – Mike 2010-09-08 05:41:59

0

嘗試首先對文件進行排序(尤其是較大的文件)。那麼你只需要檢查b中每一行的前幾個字符,並在你過去那個前綴時停下來(轉到a中的下一行)。然後你甚至可以在文件中的每個字符是第一個(a開始在第0行,b開始在第1337行,c在第13986行等等)索引。

0

嘗試使用ob_flush()flush()循環。

foreach($small_list as $one_line) 
{ 
if(stristr($big_list, $one_line) != FALSE) 
    { 
    fwrite($fh, $one_line); 
    echo "record found: " . $one_line ."<br>"; 
    } 
     @ob_flush(); 
     @flush(); 
     @ob_end_flush(); 
} 
+0

這將如何加快搜索速度? – 2010-09-08 04:56:14