目前,我正试图找到在java中搜索2GB二进制文件的最快方法。这与我的正常问题不同,因为这个文件已经被内存映射到使用mmap的Linux文件系统中。
这个文件是一个二进制文件,我需要搜索一个固定的四字节字符串;AXL0
通常,对于较小的文件,我只需缓冲它,将其转换为字符串,然后再对其进行正则化。然而,由于这个文件已经被内存映射,并且相当大,重新缓冲它的想法似乎是错误的,并且也把它转换成一个2GB的字符串似乎更错误.
在阅读了一些之后,我看到了JavaNIO包以及FileChannels和MappedByteBuffers,但我不完全确定如何设置它们。
我只需要扫描文件,从文件中的零到最后一个字节,并找到每个四个字节字符串的实例。
如果有人能提供一些建议或意见,我将非常感激。
谢谢。
发布于 2015-04-21 14:36:49
从抽象的角度看任务,你不能做比线性搜索更好的事情了。
接下来,您使用哪个API来实际执行搜索不太重要,为了简单起见,我只需要使用一个缓冲的InputStream,它可以实现与实际数据源无关的功能,并且没有固有的限制可以阻止它处理大于2GB的文件。
只要您选择了一个合理的缓冲区大小(读:不要太小),您就应该获得合理的性能(接近实际的I/O速度限制,除非是SSD,因为在这种情况下扫描的时间可能比实际的I/O要长)。
编辑:下面的吻,你得到了几行代码,应该做得很好。
public class ScanForByteCombo {
public static List<Long> scanFor(InputStream is, int needle) throws IOException {
List<Long> foundOffsets = new ArrayList<>();
InputStream bs = new BufferedInputStream(is, 0x10000);
int data = 0;
int b;
long offset = 0;
while ((b = bs.read()) != -1) {
data = (data << 8) | b;
if (data == needle)
foundOffsets.add(offset);
++offset;
}
return foundOffsets;
}
public static void main(String[] argv) {
int needle = ('A' << 24) | ('X' << 16) | ('F' << 8) | '0';
long start = System.currentTimeMillis();
try (InputStream is = new FileInputStream("your file")) {
List<Long> found = scanFor(is, needle);
System.out.println(found);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("scan took " + (System.currentTimeMillis() - start) + "ms. Acceptable?");
}
}虽然它看起来非常低效,但您可能需要付出很大的努力才能真正提高性能,这是值得注意的。
https://stackoverflow.com/questions/29774584
复制相似问题