Java Scanner.nextLine()使用换行符

时间:2012-02-10 15:14:15

标签: java regex

我有一个正在处理InputStream的扫描仪设置。

我使用Scanner.nextLine()前进到每一行,然后在每一行上做一些正则表达式。

我有一个正则表达式,它基本上像[\w\p{Z}]+?[;\n\r]一样,可以在该行的末尾拾取任何内容,或者只有一个东西,如果它们是以冒号分隔的。

所以如果我的InpustStream看起来像

abcd;
xyz

它将获取abcd;,但不是xyz。

我认为这是因为当调用.nextLine()函数时,扫描程序正在消耗文本行末尾的换行符必须以某种方式消耗掉。有谁能告诉我如何解决这个问题?

作为一个额外的信息点,对于我的正则表达式,我正在用Pattern.DOTALL编译模式

谢谢!

5 个答案:

答案 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之一,但是如果你还记得这两个关键点,你可以大大减轻使用它的痛苦:

  1. 考虑匹配分隔符,而不是字段(就像使用String的split()一样)。
  2. 如果没有先调用相应的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'。