正则表达式的扫描程序无法读取整个文件

Scanner with Regex not reading the entire file

提问人:C0DeX 提问时间:8/26/2020 更新时间:8/26/2020 访问量:117

问:

这是我的解析方法。

public void loadInput(File fileName) throws IOException {
    try {
      Scanner s = new Scanner(fileName);
      int numWords = 0;
      while (s.hasNext("(?<!')[\\w']+")) {
        System.out.println("word:" + s.next());
        numWords++;
      }
      System.out.println("Number of words: " + numWords);
    } catch (IOException e) {
      System.out.println("Error accessing input file!");
    }
  }

下面是一个示例输入文件:

Alice was beginning to get very tired of sitting by her sister
on the bank, and of having nothing to do:  once or twice she had
peeped into the book her sister was reading, but it had no
pictures or conversations in it, `and what is the use of a book,'
thought Alice `without pictures or conversation?'

  So she was considering in her own mind (as well as she could,
for the hot day made her feel very sleepy and stupid), whether
the pleasure of making a daisy-chain would be worth the trouble
of getting up and picking the daisies, when suddenly a White
Rabbit with pink eyes ran close by her.

它只匹配以下单词:

word:Alice
word:was
word:beginning
word:to
word:get
word:very
word:tired
word:of
word:sitting
word:by
word:her
word:sister
word:on
word:the
Number of words: 14

不知何故,扫描仪认为它已经到达了文件的末尾,但事实并非如此。关于为什么会发生这种情况的任何想法?我检查了我的正则表达式,它似乎确实有效(A 单词包含字母 a-z 和撇号)。谢谢!

Java 正则表达式 java.util.scanner

评论

2赞 Aaron 8/26/2020
请注意,解析器未解析的第一个单词 ,也是文本中的第一个单词,其后跟一个既不是字母也不是空格的字符(在本例中为逗号)bank

答:

1赞 jb. 8/26/2020 #1

扫描仪将文本划分为“标记”。默认标记分隔符为空格。当您的程序停止时,当前标记是 当您将其与 .hasNext() 正则表达式进行比较时,由于末尾有额外的逗号,它不匹配。bank,

解决方案可能是对 .hasNext() 和 .next() 方法使用空格标记分隔符来保留扫描程序,并在 println 语句上应用正则表达式。

while(s.hasNext()) {
   Matcher m = wordPattern.matcher(s.next());
   if (m.find()) {
       System.out.println("word:" + m.group(0))
   }
}
1赞 rzwitserloot 8/26/2020 #2

扫描仪的 hasNext 大多没用。

扫描仪的工作原理如下:

  1. 在相关任何时候(在任何 / 呼叫中,或在任何呼叫中,但不是 ,确保扫描程序知道“队列中的下一个令牌”。如果还没有,请从提要中读取另一个令牌。这是通过完全忽略请求的内容来完成的,而是扫描流结束“分隔符”(默认情况下,它是“任何空格”)。到那时为止的一切都是下一个令牌。next()nextX()hasNextnextLine()
  2. hasX() 检查排在后面的标记,并根据它是否匹配返回 true 或 false。这与是否有任何数据可供读取无关。
  3. nextLine 忽略了所有这些,并且不能很好地与扫描仪中的任何其他内容配合使用。

所以,你调用的是 hasNext,而 hasNext 忠实地报告:好吧,下一个令牌是,这与正则表达式不匹配,所以返回 .正如文档所说。bank,false

溶液

忘了hasX,你不想要那些。你也永远不想要 nextLine。如果分隔符不好,则更改分隔符(即永远不要调用 nextLine,而是调用 和 )并调用 .nextX() 方法,则扫描程序效果最佳。这就是你用它所做的一切。useDelimiter("\r?\n")next()

因此,只需调用,检查它是否匹配,然后继续。next()