我想有效地将​​正则表达式应用于整个文件

Jak*_*ake 7 java regex

我有一个复杂的正则表达式,我想将它与整个巨大文件的内容相匹配.主要关注的是效率,因为文件确实非常大并且内存不足是一种明显的可能性.

有没有办法我可以通过正则表达式匹配器以某种方式"缓冲"内容?

Dav*_*ock 6

是的,Pattern.match()会采取一个CharSequence.

如果你的输入已经在一个charset中,它只使用2个字节来表示没有任何'prologue'的字符,你只需要:

ByteBuffer bb = ...; // acquire memory mapped byte buffer
CharBuffer cb = bb.asCharBuffer();  // get a char[] 'view' of the bytes
Run Code Online (Sandbox Code Playgroud)

......自从CharBuffer实施以来CharSequence,你就完成了.

另一方面,如果您需要将字节解码为其他字符集,那么您将完成工作,因为它CharBuffer是charset-agnostic,并且在 CharsetDecorder.decode(ByteBuffer)内部分配一个CharBuffer与输入字节大致相同的新大小.

你是否能够使用更小的缓冲区取决于你的正则表达式以及你想对匹配结果做些什么.但基本的方法是实现CharSequence和包装内存映射ByteBuffer,一个小CharBuffer的"工作空间",和CharsetDecoder.您将使用Charset.decode(ByteBuffer,CharBuffer,boolean)"按需"解码字节,并希望正则表达式匹配器的大致方向是"前进",并且您感兴趣的输入是相当小的块.

作为一个粗略的开始:

class MyCharSequence implements CharSequence {

    public MyCharSequence(File file, Charset cs, int bufferSize) throws IOException {

        FileInputStream input = new FileInputStream(file);
        FileChannel channel = input.getChannel();
        this.fileLength = (int) channel.size();
        this.bytes = channel.map(FileChannel.MapMode.READ_ONLY, 0, fileLength);
        this.charBuffer = CharBuffer.allocate(bufferSize);
        this.decoder = cs.newDecoder();

    }

    public int length() {
        // ouch! have to decode the lot, even if you don't choose to keep it all handy
    }

    public char charAt(final int index) {
        while ( /* not yet decoded target char[] */ )  {
            this.decoder.decode(this.bytes, this.charBuffer, true);
        }
        // don't assume 2-bytes == a char unless that's true for your charset!
    }

    public CharSequence subSequence(final int start, final int end) {
        // this'll be fun, too
    }

    private long fileLength;
    private MappedByteBuffer bytes;
    private CharBuffer charBuffer;
    private CharsetDecoder decoder;

}
Run Code Online (Sandbox Code Playgroud)

将一个完全解码的包装CharBuffer在一个更简单CharSequence的自己的包装器中,并记录如何为您的给定输入实际调用方法可能是有益的,当您在开发盒上使用大堆运行它时.这将使您了解此方法是否适用于您的特定方案.

  • 要快点:-)另外,[http://java.sun.com/developer/technicalArticles/releases/nio/]很有用,特别是关于"映射文件"的部分. (2认同)