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;
}
# 1 楼答案
我不懂Java,但您是否希望匹配文件的全部内容,比如
/^.+$/
或者文件是根据你的正则表达式分成块的,但你不知道在哪里
正则表达式引擎很有趣,如果它能处理内存映射文件,那将是一个好的开始
让我们看看你的正则表达式。通常,您可以检查一个正则表达式,确定两个锚定点,并将其用作浮动缓冲区的截止点,在浮动缓冲区中,溢出(重叠)会被转移,窗口会在文件中进一步向下移动
我已经在Perl模块中多次这样做了。除了文件开头和结尾的锚之外,其他任何东西都很容易做到
# 2 楼答案
是的,
Pattern.match()
将需要CharSequence
如果您的输入已经在一个字符集中,该字符集只使用2个字节来表示一个没有任何“序言”的字符,那么您只需要:
。。。既然
CharBuffer
实现了CharSequence
,你就完成了另一方面,如果您需要将字节解码成其他字符集,您的工作就会被删掉,因为
CharBuffer
与字符集无关,并且CharsetDecorder.decode(ByteBuffer)
在内部分配一个新的CharBuffer
大小与输入字节大致相同你是否能用更小的缓冲区逃脱惩罚,很大程度上取决于你的正则表达式和你想对匹配结果做什么。但是基本的方法是实现
CharSequence
并包装内存映射ByteBuffer
,较小的CharBuffer
用于“工作空间”,以及CharsetDecoder
。您将使用Charset.decode(ByteBuffer,CharBuffer,boolean)
来“按需”解码字节,并希望正则表达式匹配器的一般方向是“向前”,并且您感兴趣的输入是以相当小的块进行的作为一个艰难的开始:
在开发框上用一个大堆运行完全解码的
CharBuffer
时,用一个更简单的CharSequence
包装器包装一个CharBuffer
完整解码的CharBuffer
,并记录对给定输入实际调用方法的方式,可能会很有帮助。这将使您了解这种方法是否适用于您的特定场景