我正在努力将 Perl 程序移植到 Java,并一边学习 Java。原始程序的核心组成部分是Perl模块 http://search.cpan.org/~jfreeman/File-SortedSeek-0.015/lib/File/SortedSeek.pm使用二分搜索在 +500 GB 排序文本文件中进行字符串前缀查找
(本质上,“查找”到文件中间的字节偏移量,回溯到最近的换行符,将行前缀与搜索字符串进行比较,“查找”到该字节偏移量的一半/两倍,重复直到找到......)
我已经尝试了几种数据库解决方案,但发现对于这种大小的数据集,在纯粹的查找速度上没有什么比这更好的了。您知道现有的 Java 库可以实现此类功能吗?如果做不到这一点,你能给我指出一些随机访问读取文本文件的惯用示例代码吗?
或者,我不熟悉新的(?)Java I/O 库,但是可以选择内存映射 500 GB 文本文件(我在一台有空闲内存的 64 位机器上)并执行二进制操作搜索内存映射字节数组?我非常有兴趣听到您分享有关此问题和类似问题的任何经验。
I am a bigJava 的粉丝MappedByteBuffers http://download.oracle.com/javase/1.5.0/docs/api/index.html?java/nio/MappedByteBuffer.html对于这样的情况。它的速度非常快。下面是我为您整理的一个片段,它将缓冲区映射到文件,查找中间,然后向后搜索到换行符。这应该足以让你继续下去吧?
我在自己的应用程序中有类似的代码(查找、读取、重复直到完成),并进行了基准测试java.io
流反对MappedByteBuffer
在生产环境中并将结果发布在我的博客上(Geekomatic 帖子标记为“java.nio” http://geekomatic.ch/tags/java.nio/)包含原始数据、图表等。
两秒总结?My MappedByteBuffer
基于 的实施速度大约提高了 275%。 YMMV.
要处理大于 ~2GB 的文件,这是一个问题,因为转换和.position(int pos)
,我精心设计了由一系列支持的分页算法MappedByteBuffer
s。您需要在 64 位系统上工作才能处理大于 2-4GB 的文件,因为 MBB 使用操作系统的虚拟内存系统来发挥其魔力。
public class StusMagicLargeFileReader {
private static final long PAGE_SIZE = Integer.MAX_VALUE;
private List<MappedByteBuffer> buffers = new ArrayList<MappedByteBuffer>();
private final byte raw[] = new byte[1];
public static void main(String[] args) throws IOException {
File file = new File("/Users/stu/test.txt");
FileChannel fc = (new FileInputStream(file)).getChannel();
StusMagicLargeFileReader buffer = new StusMagicLargeFileReader(fc);
long position = file.length() / 2;
String candidate = buffer.getString(position--);
while (position >=0 && !candidate.equals('\n'))
candidate = buffer.getString(position--);
//have newline position or start of file...do other stuff
}
StusMagicLargeFileReader(FileChannel channel) throws IOException {
long start = 0, length = 0;
for (long index = 0; start + length < channel.size(); index++) {
if ((channel.size() / PAGE_SIZE) == index)
length = (channel.size() - index * PAGE_SIZE) ;
else
length = PAGE_SIZE;
start = index * PAGE_SIZE;
buffers.add(index, channel.map(READ_ONLY, start, length));
}
}
public String getString(long bytePosition) {
int page = (int) (bytePosition / PAGE_SIZE);
int index = (int) (bytePosition % PAGE_SIZE);
raw[0] = buffers.get(page).get(index);
return new String(raw);
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)