perl处理文本文件抛出out of memory

造成问题的原因是处理的文本文档有2g大小。

#2016.10.21 by ouyanga
#合并所有的词频文件到$result目录下de最终词频

my $fileDir=shift @ARGV or die "$!";
my $result;

$result=$fileDir."\\最终词频";

mkdir $result;

my $filepath=$fileDir."\\文件名.log";
my @dir; 

opendir (DIR, $fileDir);
@dir = readdir DIR;

open(out1, ">$filepath"); #输入

foreach $file (@dir) 
{ 
       if( $file =~ /\.txt$/)
    {
        print out1 $fileDir."\\".$file."\n";
    } 

} 
close(out1);

open (in2,$filepath);

#遍历包含文件名的列表
while($filename=<in2>){
    chomp($filename);
    
    print "read file ".$filename."\n";
    
    open(inTmp2, $filename) or die "cannot open ".$filename."\n";

    while(defined($word=<inTmp2>)){
        chomp($word);
        
        split("\t",$word);
                
        $words{$_[0]}+=$_[1];
            
    }
    close(inTmp2);
}
close(in2);

$result=$result."\\最终词频.txt";

open(out2,">".$result) or die "can not open". $result."\n";

foreach $w (sort keys %words){
    print out2 $w."\t".$words{$w}."\n";
}
close(out2);

print "game over.\n";

 解决方法:

对文件的内容进行hash,分解成多个小文件。

然后合并小文件里面重复的词。

再把小文件写到一个文件里面。

#2016.10.21 by ouyanga
#1.顺序读取文件,对于每个词Hash(x)%31。然后按着值存放到31个文件中。
#2.针对每个文件,统计词以及频率
#3.合并31个文件为一个文件

use Encode; 
my $fileDir=shift @ARGV or die "$!";#包含待处理文件的目录
my $result;

$result=$fileDir."\\分而治之";

mkdir $result;

my $filepath=$fileDir."\\文件名.log";
my @dir; 

opendir (DIR, $fileDir);
@dir = readdir DIR;

open(out1, ">$filepath"); #输入

foreach $file (@dir) 
{ 
       if( $file =~ /\.txt$/)
    {
        # 统计目录下得所有文件
        print out1 $fileDir."\\".$file."\n";
    } 

} 

close(out1);

open (in2,$filepath);

my $hash_value=31;
my %result_dir;

my $hashValue=31;
while($hashValue!=-1)
{
    $result_dir{$hashValue}="hash".$hashValue.".txt";
    --$hashValue;
}

#遍历包含文件名的列表
while(defined($filename=<in2>)){

    chomp($filename);
    
    print "read file ".$filename."\n";
    
    open(inTmp2, $filename) or die "cannot read open ".$filename."\n";

    # 对文件里面的词进行hash映射
    while(defined($word=<inTmp2>)){
        chomp($word);
        
        split(/\t/,$word);
        
        my $str=decode("gb2312",$_[0]); 

        @chars=split (//,$str);
     
        my $c=0;    #=ord($chars[0]);#ord把gb2312编码转为十进制。
        
        foreach $tc(@chars){
                                
            $c=$c*31+ord($tc);
        }
        
        $hash_value= $c%31;
        
        my $resultTxt=$result."\\".$result_dir{$hash_value};
        
        open(out2,">>".$resultTxt) or die "can write not open ". $resultTxt.". calcultate hash value is : $hash_value.\n";#追加内容
        
        print out2 $word."\n";
        
        close(out2);
    }
    
    close(inTmp2);
}

close(in2);

print "game over.\n";

 

posted @ 2016-10-21 10:43  viola  阅读(1343)  评论(0编辑  收藏  举报