我有一个正在处理InputStream的扫描仪设置。
我使用Scanner.nextLine()前进到每一行,然后在每一行上做一些正则表达式。
我有一个正则表达式,它基本上像[\w\p{Z}]+?[;\n\r]
一样,可以在该行的末尾拾取任何内容,或者只有一个东西,如果它们是以冒号分隔的。
所以如果我的InpustStream看起来像
abcd;
xyz
它将获取abcd;,但不是xyz。
我认为这是因为当调用.nextLine()函数时,扫描程序正在消耗文本行末尾的换行符必须以某种方式消耗掉。有谁能告诉我如何解决这个问题?
作为一个额外的信息点,对于我的正则表达式,我正在用Pattern.DOTALL编译模式
谢谢!
答案 0 :(得分:5)
实际上,你是那个导致问题的人,试图在最后一行的末尾使用换行符。 : - /它完全有效,最后一行突然结束没有换行符,但你的正则表达式要求它有一个。您可以通过使用锚点或前瞻替换换行符来解决这个问题,但是有更简单的方法可以解决这个问题。
一种方法是覆盖默认分隔符并使用next()
迭代字段:
Scanner sc1 = new Scanner("abcd;\nxyz");
sc1.useDelimiter("[;\r\n]+");
while (sc1.hasNext())
{
System.out.printf("%s%n", sc1.next());
}
另一种方法是使用nextLine()
(使用默认分隔符)迭代这些行,然后用分号分隔每一行:
Scanner sc2 = new Scanner("abcd;\nxyz");
while (sc2.hasNextLine())
for (String item : sc2.nextLine().split(";"))
{
System.out.printf("%s%n", item);
}
扫描仪的API是我曾经使用过的最臃肿和不直观的API之一,但是如果你还记得这两个关键点,你可以大大减轻使用它的痛苦:
split()
一样)。nextXXX()
方法,请勿调用其中一个hasNextXXX()
方法。答案 1 :(得分:2)
那么,为什么不在nextLine()
结果中添加换行符?
是否存在正则字符^
或$
代表字符串边界?
答案 2 :(得分:1)
正则表达式字符$
找到“模式的结尾”。话虽如此,因为你没有行尾字符,所以在第一个分号之前很容易消耗所有东西;只消耗除分号以外的所有内容:
[^;]+
Scanner
使用换行符作为其行为的一部分,因为您通常不想处理它,并且它依赖于系统。
编辑:在评论中有人指出你可以使用line.split(";")
并获取第一个值。这也可以。
答案 3 :(得分:1)
API明确指定下一行删除任何行分隔符nextLine()
您可以在其他回复中执行各种建议之一。但请注意,扫描仪的方法有“模式”。所以如果你的正则表达式是正确的,你可以使用以下方法:
hasNext(Pattern pattern)或hasNext(String pattern)查找您是否有更多令牌
然后
next(Pattern pattern)或next(String pattern)如果上述内容返回true,则获取令牌。
答案 4 :(得分:0)
您可以在正则表达式模式中使用\z
来表示输入的结尾,或者$
表示行的结尾。此外,默认情况下,Scanner.nextLine()
会返回行,而不是换行符。此外,您可以更改Scanner
使用的分隔符,以使;
方法包含useDelimiter
。最后,您的模式可能无法按照您的想法执行,因为\p{Z}
仅根据documentation for Pattern
捕获字母'Z'。