【问题标题】:Large file substring extraction, avoiding line terminators大文件子字符串提取,避免行终止符
【发布时间】:2012-03-30 10:11:31
【问题描述】:

问题如下:

几个大文件 (20+ MB) 中包含 DNA 序列。我使用以下代码连接到这些文件:

fc = FileChannel.open(file);

// Create a read-only CharBuffer on the file
ByteBuffer bbuf = fc.map(FileChannel.MapMode.READ_ONLY, 0, 256);
CharBuffer cbuf = Charset.forName("8859_1").newDecoder().decode(bbuf);

我知道要提取的子序列的确切开始和结束位置,这将允许我使用该方法

cbuf.subSequence(start, end);

但是,大文件的行终止符会破坏 DNA 序列,因此它们算作一个字符。不建议假定文件中行的固定宽度。什么是“跳过”行终止符的有效方法,但通过使用 Charbuffer 或类似的东西来保持内存效率?

我已经尝试使用带有正则表达式的贪婪量词,但行终止符又一次破坏了结果。我想不惜一切代价避免完全加载文件内容。有没有办法将换行符视为“不存在”?

【问题讨论】:

  • 内存效率真的那么重要吗? 20 MB 不是那么大。数据集总共有多大?
  • 这是 C/C++ 还是您使用的是什么语言?
  • 编程语言是Java。关于内存效率,文件的处理只是我的程序必须完成的几项任务之一。如果加载整个文件,最好的策略是什么?对于我必须提取的序列数量有些稀疏,删除所有 '\n' 分隔符似乎相当多。
  • DNA 序列不会创建像“无数”字节的文件吗?如果不需要,您是否应该避免加载整个文件?

标签: java newline large-files


【解决方案1】:

您可以读取文件,查找行终止符并存储它们的位置。

然后在提取时,您可以将没有终结符的位置转换为实际位置。

为了更快地转换,您可以预先计算偏移量,然后只需搜索正确的偏移量(O(long n),其中 n 是行终止符的总数,而 O(m) 是您实际需要跳过的终止符的数量)

PS:考虑一下多字符(CR,LF)终止符,如果可能的话。

【讨论】:

  • 我已经应用了这个解决方案,它可能是整体上最好的。提取信息的预处理步骤,用于加速主搜索中的序列提取。
【解决方案2】:

DNA 序列不会创建类似于“无数”(大量)字节的文件吗?如果不需要,也许您应该避免加载整个文件?您的变量 cbuf 中似乎有一些数据(我不知道那是什么数据;您的代码没有说明)。我认为您可以编写一个函数来删除换行符,例如:

int index = 0;
for(int i = 0; i < cbuf.length; i++)
{
   if(!cbuf[i] != '\n' && cbuf[i] != '\r')
   {
      cbuf[index] = cbuf[i];
      index++; // will only increase if not linebreak
   }
}

int newcbufLength = index + 1;

此函数将使用原始数组,因此您不会有数据的新(大?)副本。

(可能会有错误,因为我最习惯 C# 而不是 Java)

【讨论】:

    猜你喜欢
    • 2021-03-09
    • 1970-01-01
    • 2021-12-23
    • 1970-01-01
    • 2020-12-29
    • 2015-12-16
    • 2013-07-14
    相关资源
    最近更新 更多