2

我正在寻找一种方法来解析大文件(大约 5-10Go)并尽可能快地搜索一些循环字符串的位置(以字节为单位)。

我尝试通过执行以下操作来使用 RandomAccessFile 阅读器:

RandomAccessFile lecteurFichier = new RandomAccessFile(<MyFile>, "r");
while (currentPointeurPosition < lecteurFichier.length()) {
     char currentFileChar = (char) lecteurFichier.readByte();
     // Test each char for matching my string (by appending chars until I found my string)
     // and keep a trace of all found string's position
}

问题是这段代码太慢了(可能是因为我逐字节读取?)。

我还尝试了下面的解决方案,它在速度方面非常完美,但我无法获得我的字符串的位置。

    FileInputStream is = new FileInputStream(fichier.getFile());

    FileChannel f = is.getChannel();

    ByteBuffer buf = ByteBuffer.allocateDirect(64 * 1024);

    Charset charset = Charset.forName("ISO-8859-1");
    CharsetDecoder decoder = charset.newDecoder();

    long len = 0;
    while ((len = f.read(buf)) != -1) {
        buf.flip();

        String data = "";
        try {
            int old_position = buf.position();
            data = decoder.decode(buf).toString();
            // reset buffer's position to its original so it is not altered:
            buf.position(old_position);
        }
        catch (Exception e) {
            e.printStackTrace();
        }

        buf.clear();
    }

    f.close();

有没有人可以提出更好的解决方案?

提前谢谢你(对不起我的拼写,我是法国人)

4

2 回答 2

1

由于您的输入数据以 8 位编码*进行编码,因此您可以通过对搜索字符串进行编码而不是对文件进行解码来加快搜索速度:

byte[] encoded = searchString.getBytes("ISO-8859-1");

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
int b;
long pos = -1;
while ((b = bis.read()) != -1) {
    pos++;
    if (encoded[0] == b) {
       // see if rest of string matches
    }
}

ABufferedInputStream应该很快。使用 ByteBuffer 可能会更快,但这会使搜索逻辑更加复杂,因为字符串匹配的可能性比跨越缓冲区边界的可能性高。

然后有各种巧妙的方法来优化可以适应这种情况的字符串搜索......您正在搜索字节/字符流而不是字节/字符数组。字符串搜索的 Wikipedia 页面是一个很好的起点。

请注意,由于我们以字节方式读取和匹配,因此位置只是读取(或跳过)的字节数,因此无需使用随机访问文件。


* 事实上,这个技巧也适用于许多多字节编码。

于 2012-11-30T17:56:22.860 回答
0

在“干草堆”中搜索“针”是一个经过充分研究的问题 - 这是 StackOverflow 本身的相关链接。我确信所讨论的算法的 java 实现也应该可用。为什么不尝试其中一些,看看它们是否适合这份工作?

于 2012-11-30T17:38:16.337 回答