这个问题还需要再具体一点,就是,
- 内存有限,不可能完全把大文本全部读入。
- 速度不能过慢。
- 题目:有两个文本文件,一个是结果文件,一个是注释文件,每个文件内每行存贮的都是以tab为间隔的数据,而其中tab数都是一致的。也就是说,文本文件可以看成是以tab为间隔的csv文件。每个文件内的第一列(以tab为分隔)都是一个不重复的关键字。要求将两个文本文件以关键字为基准合并起来。
我的思路是:
- 将注释文件建立索引
- 逐行读取结果文件并注释。
有人说,可以先对两个文件排序,然后再合并。这个方案我也考虑过,但是觉着不如前面的这个思路好。这只是个思路,算不上算法,所以只能说勉强可以完成要求。
#getIndex(),by jianhong from qiuworld.com #建立索引数组, #array的key是文本中第一列的关键字, #value是文本文件距文件起始位置的偏移地址。 function getIndex($ifh,$delimiter){ $res = fopen($ifh, 'r') or die("can not open $ifh"); $res_index=array(); $pos=0; while(($line=fgetcsv($res,4096,$delimiter))!==false){ $res_index[$line[0]]=$pos; $pos=ftell($res); } fclose($res); return $res_index; } #合并结果文件与注释文件 function getAnnotation($ifh,$afh,$ofh,$delimiter){ $ann_index=getIndex($afh,$delimiter); $res = fopen($ifh, 'r') or die("can not open $ifh"); $ann = fopen($afh, 'r') or die("can not open $afh"); $merged = fopen($ofh, 'w') or die("can not open $ofh"); #合并表头 $line1=fgets($res); $line2=fgets($ann); fputs($merged,chop($line1).$delimiter.$line2); #合并内容 while(($line1=fgetcsv($res))!==false){ if(isset($ann_index[$line1[0]])){ fseek($ann, $ann_index[$line1[0]]); if(($line2=fgetcsv($ann,4096,$delimiter))!==false) fputcsv($merged,array_merge($line1,$line2),$delimiter); else fputcsv($merged,$line1,$delimiter); } else fputcsv($merged,$line1,$delimiter); } fclose($res); fclose($ann); fclose($merged); } #调用 getAnnotation("results.file.name","annotation.file.name","output.file.name","\t"); |