有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java我希望对整个文件有效地应用正则表达式

我有一个复杂的正则表达式,我想将它与整个大型文件的内容相匹配。主要关注的是效率,因为文件确实非常大,并且很可能会耗尽内存

有没有一种方法可以在通过正则表达式匹配器泵送内容时以某种方式“缓冲”内容


共 (2) 个答案

  1. # 1 楼答案

    我不懂Java,但您是否希望匹配文件的全部内容,比如/^.+$/
    或者文件是根据你的正则表达式分成块的,但你不知道在哪里
    正则表达式引擎很有趣,如果它能处理内存映射文件,那将是一个好的开始

    让我们看看你的正则表达式。通常,您可以检查一个正则表达式,确定两个锚定点,并将其用作浮动缓冲区的截止点,在浮动缓冲区中,溢出(重叠)会被转移,窗口会在文件中进一步向下移动

    我已经在Perl模块中多次这样做了。除了文件开头和结尾的锚之外,其他任何东西都很容易做到

  2. # 2 楼答案

    是的,Pattern.match()将需要CharSequence

    如果您的输入已经在一个字符集中,该字符集只使用2个字节来表示一个没有任何“序言”的字符,那么您只需要:

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

    。。。既然CharBuffer实现了CharSequence,你就完成了

    另一方面,如果您需要将字节解码成其他字符集,您的工作就会被删掉,因为CharBuffer与字符集无关,并且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;
    
    }
    

    在开发框上用一个大堆运行完全解码的CharBuffer时,用一个更简单的CharSequence包装器包装一个CharBuffer完整解码的CharBuffer,并记录对给定输入实际调用方法的方式,可能会很有帮助。这将使您了解这种方法是否适用于您的特定场景