【问题标题】:Parsing huge text file in Perl在 Perl 中解析巨大的文本文件
【发布时间】:2023-03-15 10:05:01
【问题描述】:

我有大约 30 GB 的基因组文件,如下所示,

>2RHet assembled 2006-03-27 md5sum:88c0ac39ebe4d9ef5a8f58cd746c9810
GAGAGGTGTGGAGAGGAGAGGAGAGGAGTGGTGAGGAGAGGAGAGGTGAG
GAGAGGAGAGGAGAGGAGAGGAATGGAGAGGAGAGGAGTCGAGAGGAGAG
GAGAGGAGTGGTGAGGAGAGGAGAGGAGTGGAGAGGAGACGTGAGGAGTG
GAGAGGAGAGTAGTGGAGAGGAGTGGAGAGGAGAGGAGAGGAGAGGACGG
ATTGTGTTGAGGACGGATTGTGTTACACTGATCGATGGCCGAGAACGAAC

我正在尝试解析文件并快速完成我的任务, 逐个字符地使用下面的代码 但是字符没有被打印出来

open (FH,"<:raw",'genome.txt') or die "cant open the file $!\n";

until ( eof(FH) ) {

$ch = getc(FH);
print "$ch\n";# not printing ch

}
close FH;

【问题讨论】:

  • 你的问题对我来说毫无意义。这取决于您要如何处理数据。
  • until(&lt;FH&gt;) 是……很不寻常。
  • 添加了错误的代码.. 刚刚更正了代码
  • 真的不清楚你想要完成什么。
  • 你没有说你想对数据做什么,但是逐个字符地读取它确实会非常慢,而且几乎可以肯定是错误的方式去做吧。

标签: perl parsing


【解决方案1】:

你的错误是忘记了eof

until (eof FH) { ... }

但这非常不太可能是最有效的解决方案:Perl 比……C 慢,所以我们希望循环迭代尽可能少,并且在 perl 内部完成尽可能多的工作我们可以得到。这意味着逐字符读取文件是

另外,使用词法变量(用my 声明)而不是全局变量;这可以提高性能。

要么选择一个自然的记录分隔符(如\n),要么读取一定数量的字节:

local $/ = \256; # read 256 bytes at a time.
while (<FH>) {
  # do something with the bytes
}

(见perlvar

您还可以摆脱openreadline 甚至getc 为您提供的所有奢侈品,并使用sysopensysread 进行全面控制。然而,这种方式是疯狂的。

# not tested; I will *not* use sysread.
use Fcntl;
use constant NUM_OF_CHARS => 1; # equivalent to getc; set higher maybe.
sysopen FH, "genome.txt", O_RDONLY or die;

my $char;
while (sysread FH, $char, NUM_OF_CHARS, 0) {
  print($char .= "\n");  # appending should be better than concatenation.
}

如果我们已经走了那么远,使用Inline::C 只是一个小步骤,可能更可取。

【讨论】:

  • 如有必要,一次将其设为 1024 或 4096 个字节。
  • 一次 1mb,Perl 可以处理。 Google 在旧 GFS 中使用了 64mb 块。
  • 我对每个进程进行了基准测试,以读取 3.2 mb 文件的文件,滑动窗口为 200 #1。 FH,"<:raw sysread tie>
  • @made_in_india 您应该会看到sysread FH, $ch, 1024 的性能进一步提高,或者通常读取多个字符。您的测量似乎非常缓慢,指出了我们无法访问的问题。查看您问题下的 Borodins 评论,并说明您的真正问题。
猜你喜欢
  • 2010-10-29
  • 1970-01-01
  • 2014-07-22
  • 1970-01-01
  • 1970-01-01
  • 2012-10-09
  • 1970-01-01
相关资源
最近更新 更多