我正在努力将Perl程序移植到Java,并在学习过程中学习Java。原始程序的核心组件是Perl模块,该模块使用二进制搜索在+500
GB排序的文本文件中执行字符串前缀查找(本质上是“寻找”到文件中间的字节偏移,回溯到最近的换行符,然后进行比较)带有搜索字符串的行前缀,“搜索”为字节偏移量的一半/两倍,重复直到找到…)
我已经尝试了几种数据库解决方案,但是发现使用这种大小的数据集,在纯粹的查找速度上没有比这更好的了。您是否知道任何实现这种功能的Java库?失败了,您能否指出一些惯用的示例代码,该示例代码会随机访问读取文本文件?
另外,我不熟悉新的Java Java I / O库,但是是否可以选择将内存映射到500
GB的文本文件(我在64位计算机上,有空闲的内存)并执行二进制操作在内存映射的字节数组上搜索?我很想听听您必须分享有关此问题和类似问题的任何经验。
我是一个 很大的 Java的风扇
MappedByteBuffers
像这样的情况。它正在迅速燃烧。下面是我为您整理的一个片段,该片段将缓冲区映射到文件,查找到中间,然后向后搜索换行符。这应该足以让您继续前进吗?
我有类似的代码(寻找,读,重复,直到完成)在我自己的应用程序,基准
java.io
针对流MappedByteBuffer
在生产环境和贴在我的博客的结果(Geekomatic文章标签“的java.nio”)与原始数据,图表和所有。
两秒钟的总结? 基于 我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);
}
}
问题 你想内存映射一个二进制文件到一个可变字节数组中,目的可能是为了随机访问它的内容或者是原地做些修改。 解决方案 使用 mmap 模块来内存映射文件。 下面是一个工具函数,向你演示了如何打开一个文件并以一种便捷方式内存映射这个文件。 import os import mmap def memory_map(filename, access=mmap.ACCESS_WRITE): siz
问题内容: 我一直在尝试编写一些非常快速的Java代码,这些代码必须执行很多I / O。我正在使用返回ByteBuffer的内存映射文件: 我遇到的问题是ByteBuffer .array()方法(应返回一个byte []数组)不适用于只读文件。我想编写我的代码,以便它可以与构造在内存中的内存缓冲区和从磁盘读取的缓冲区一起使用。但是我不想将所有缓冲区都包装为ByteBuffer.wrap()函数,
问题内容: 我在将这两种算法结合在一起时遇到麻烦。我被要求修改以返回将元素插入数组的索引。然后有人要求我实现一个使用my 对随机生成的数组进行排序的。 我按照预期的方式工作,每当我单独测试它时都返回正确的索引。我写信是为了了解它是如何工作的,并使其也能工作。一旦将两者结合在一起,它就会崩溃。我知道我在一起实施起来不正确,但是我不确定问题出在哪里。 这是我得到的: 我在运行它时得到的返回值是。有什么
问题内容: 最近,我碰到了这篇文章,这篇文章很好地介绍了内存映射文件以及如何在两个进程之间共享它。这是读取文件的过程的代码: 但是,我对这种方法有几点评论/问题: 如果我们仅对空文件执行读取器,即运行 这将分配8000个字节,现在将扩展文件。返回的缓冲区的限制为8000,位置为0,因此,读取器可以继续读取空数据。发生这种情况后,阅读器将停止,如。 现在应该是作家了(代码被省去了,因为它很简单,可以
问题内容: 我被要求对数组进行排序和搜索。对数组进行排序很简单,我的代码也起作用了,但是每当我尝试调用二进制搜索方法时,它就可以对数组中的第一个元素起作用,但是结果是“ -1” 我的完整代码如下: 问题答案: 您搞砸了二进制搜索间隔
我有一个映射,其中FullName是一个对象,包含另一个类名为FirstName和LastName的对象。名字和姓氏是字符串。(是的,我知道这是一个糟糕的设计,但我正在努力学习排序) 密钥字符串只是id,比如1,2,3,。。。 我想根据全名(名字和姓氏)进行排序,然后返回一个id列表。 这是我到目前为止的代码,但我在传递比较器的排序部分遇到语法错误。而且我很确定我在做一些语义上不正确的事情。