使用\ R模式的Java扫描程序使用(缓冲区边界问题)

问题描述 投票:10回答:1

执行摘要:在Java的\R中使用Scanner(或其他正则表达式模式)是否有任何警告/已知问题(特别是关于内部缓冲区的边界条件)?

细节:由于我想在潜在的多平台输入文件上进行一些多线模式匹配,我使用了\R的模式,根据Pattern javadoc,它是:

任何Unicode换行符序列都等同于\u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]

无论如何,我注意到在我的一个测试文件中,应该解析一个十六进制转储块的循环被缩短了。经过一些调试后,我注意到它结束的那一行是Scanner内部缓冲区的结束。

这是我写的一个测试程序来模拟这种情况:

public static void main(String[] args) throws IOException {
    testString(1);
    testString(1022);
}

private static void testString(int prefixLen) {
    String suffix = "b\r\nX";
    String buffer = new String(new char[prefixLen]).replace("\0", "a") + suffix;

    Scanner scanner = new Scanner(buffer);
    String pattern = "b\\R";
    System.out.printf("=================\nTest String (Len=%d): '%s'\n'%s' found with horizon=0 (w/o bound): %s\n", buffer.length(), convertLineEndings(
        buffer), pattern, convertLineEndings(scanner.findWithinHorizon(pattern, 0)));
    System.out.printf("'X' found with horizon=1: %b\n", scanner.findWithinHorizon("X", 1) != null);
    scanner.close();
}

private static String convertLineEndings(String string) {
    return string.replaceAll("\\n", "\\\\n").replaceAll("\\r", "\\\\r");
}

...产生此输出(为格式化/简洁而编辑):

=================
Test String (Len=5): 'ab\r\nX'
'b\R' found with horizon=0 (w/o bound): b\r\n
'X' found with horizon=1: true
=================
Test String (Len=1026): 'a ... ab\r\nX'
'b\R' found with horizon=0 (w/o bound): b\r
'X' found with horizon=1: false

对我来说,这看起来像一个错误!我认为扫描仪应该与suffix相匹配,模式与输入文本中显示的位置无关(只要prefix不参与模式)。 (我也发现了可能相关的Open JDK Bugs 81764078072582,但这是常规的Oracle JDK 8u111)。

但是我可能已经错过了一些关于扫描器或特定\R模式使用的建议(或Open JDK,以及Oracle在这里对相关类有相同的(??)实现?)...因此问题!

java regex java.util.scanner
1个回答
0
投票

两个建议:

我认为你应该以这种方式测试X:

System.out.printf("'X' found with horizon=1: %b\n", 
    scanner.findWithinHorizon("X", prefixLen) != null);

(因为除0之外的任何东西作为水平参数将搜索限制为一定数量的字符。这已经在方法的名称中。视野范围就是方法所见。)

也许你的文件编码有问题。您的扫描仪可能会选择错误的默认编码。尝试沿着这条线:

new Scanner(file, "utf-8");
© www.soinside.com 2019 - 2024. All rights reserved.