2010-09-08 75 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