首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java内存映射二进制搜索

Java内存映射二进制搜索
EN

Stack Overflow用户
提问于 2015-04-21 14:06:05
回答 1查看 360关注 0票数 4

目前,我正试图找到在java中搜索2GB二进制文件的最快方法。这与我的正常问题不同,因为这个文件已经被内存映射到使用mmap的Linux文件系统中。

这个文件是一个二进制文件,我需要搜索一个固定的四字节字符串;AXL0

通常,对于较小的文件,我只需缓冲它,将其转换为字符串,然后再对其进行正则化。然而,由于这个文件已经被内存映射,并且相当大,重新缓冲它的想法似乎是错误的,并且也把它转换成一个2GB的字符串似乎更错误.

在阅读了一些之后,我看到了JavaNIO包以及FileChannelsMappedByteBuffers,但我不完全确定如何设置它们。

我只需要扫描文件,从文件中的零到最后一个字节,并找到每个四个字节字符串的实例。

如果有人能提供一些建议或意见,我将非常感激。

谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-04-21 14:36:49

从抽象的角度看任务,你不能做比线性搜索更好的事情了。

接下来,您使用哪个API来实际执行搜索不太重要,为了简单起见,我只需要使用一个缓冲的InputStream,它可以实现与实际数据源无关的功能,并且没有固有的限制可以阻止它处理大于2GB的文件。

只要您选择了一个合理的缓冲区大小(读:不要太小),您就应该获得合理的性能(接近实际的I/O速度限制,除非是SSD,因为在这种情况下扫描的时间可能比实际的I/O要长)。

编辑:下面的吻,你得到了几行代码,应该做得很好。

代码语言:javascript
复制
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?");
    }

}

虽然它看起来非常低效,但您可能需要付出很大的努力才能真正提高性能,这是值得注意的。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29774584

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档