免费注册 查看新帖 |

Chinaunix

广告
  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 8378 | 回复: 28
打印 上一主题 下一主题

在Perl中怎么实现利用缓冲区读写文件?? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-07-21 11:15 |只看该作者 |倒序浏览
大家好,我在用perl分析处理大文本的时候(有10GB),刚开始实现的是逐条读取,分析后直接写入另外一个文本,

后来感觉耗时太长,就想通过设置Perl的缓冲区去读1000行,在去写1000行,然后再读1000,再写。。。。。
理论上减少的I/O,会提高一些效率,但具体怎么实现,我就不知道了,我查了好多资料,都没有解决,希望遇到过这样问题的已经解决的朋友,
或者对这些方面有研究的朋友给出指导。

我的代码如下:

sub formatlog {
    my ($fromfile, $tofile) = @_;
    my @linelog = ();

    my $line = " ";
    my $strn = " ";
    open(FILE1, $fromfile)  || die "can not open the $fromfile: $!";
    open(FILE2, ">$tofile") || die "can not create the $tofile: $!";
    #print "begin transform log filefromfile-->$tofile \n";

    while (defined($eachline = <FILE1>;)) {
        chomp $eachline;

        if (substr($eachline,0,3) ne "HDR") {

            #生成固定序列的hash

            ####################################


            #print "testrowlog \n";


            @linelog =();
            @linelog = &get_cnct_nbr($eachline);

            ###################################

            binmode FILE2;
            $numbers = " ";
            $line = " ";
            $strn = " ";
            $numbers = join( '|', @rowlog ) . "\n";
            ######################################

            #测试新生成的log  BEGIN

            ######################################

                        
            #影响效率的代码,需要重新确认

        #print "aaaaaaaaalinelog[2]\n";

            
            
            $line = join('|',@linelog);
            #print "@linelog \n";

            $strn = $line."\n";

            ######################################

            #测试新生成的log  END

            #####################################


            print FILE2 $strn;
            @rowlog =();    #对每次循环的数组一定要清空,否则就会在非空的基础上添加元素

        }
    }
    close FILE1;
    close FILE2;
    #print "finish transform log filefromfile-->$tofile \n";

    return;
}

论坛徽章:
0
2 [报告]
发表于 2008-07-21 17:55 |只看该作者
我也遇到这个问题,忘高手赐教

论坛徽章:
0
3 [报告]
发表于 2008-07-21 21:57 |只看该作者
读的的话不知道有什么好办法。
写的话,可不可以把1000行放在一个@中,然后一次flush到写入文件。 不知道这样会不会快点。

论坛徽章:
0
4 [报告]
发表于 2008-07-21 21:58 |只看该作者
期待flw给出方法

论坛徽章:
0
5 [报告]
发表于 2008-07-21 23:05 |只看该作者
学习,等待solution。。。

论坛徽章:
0
6 [报告]
发表于 2008-07-22 10:13 |只看该作者

回复 #3 forlorngenius 的帖子

但是如果把读出来的数据放到缓存中处理效率可能才高,然后在将处理后的数据写入文本。另外怎么设置每次能够读取1000行数据呢?具体实现我也在考虑,如果通过计数器去判断的话,可能效率会很低,另外,也可能会遗漏一些数据。

比如

....
my $cnt = 0;

while (defined($eachline = <FILE1>) {
      ....
      $cnt++;
     if($cnt==1000)
     {
            #写入数据到文件
       $cnt = 0;
      }
      ....
}

论坛徽章:
0
7 [报告]
发表于 2008-07-22 10:28 |只看该作者

回复 #6 houyawei 的帖子

可以用$.对行数进行处理。判断$.被1000整除或eof,一直读,读的话好像就是一直buffer的,buffer size好像是8k。
读了1000行后,试着存入一个临时的$line,再将这$line直接写入文件,用select output_FH; $|=1;关闭buffer。
试下看看。嗬嗬,我乱想的

论坛徽章:
0
8 [报告]
发表于 2008-07-22 12:13 |只看该作者
删了,不害人了

[ 本帖最后由 forlorngenius 于 2008-7-22 15:35 编辑 ]

论坛徽章:
0
9 [报告]
发表于 2008-07-22 15:06 |只看该作者

回复 #8 forlorngenius 的帖子

我刚刚用你的代码,测试了360MB差不多210万行的数据,跑了N久都没有出来,只见内存飞涨。
我用读一行写一行的方法,7秒左右就出来了。

3万的数据量2种方法的耗时差不多。

我想要的目的有3个方面:
1.怎么快速1000行读取文件到内存?
2.读文件的方式只能是一行一行的读取么?有没有其余的读取装载到内存的方式?
3.写文件的方式只能是一行一行的写么?


我的测试代码是:
#!/usr/bin/perl
print "耗时测试开始:\n";
$date_tst = localtime(time);
print "$date_tst \n";
open ( readfile , "30000_a.txt") or die ("Could not open the filen");
open ( writefile , ">b2.txt" );
while( $line = <readfile> )
{
    print writefile $line;
}
close( writefile );
close( readfile );
print "耗时测试结束:\n";
$date_tst = localtime(time);
print "$date_tst \n";

论坛徽章:
0
10 [报告]
发表于 2008-07-22 15:21 |只看该作者
我也是觉得,读一行写一行,速度很快的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP