带有正则表达式的扫描仪不读取整个文件
Scanner with Regex not reading the entire file
这是我的解析方法。
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-z 和撇号)。谢谢!
扫描器正在将文本分成“标记”。默认的标记分隔符是空格。当您的程序停止时,当前标记为 bank,
当您将其与您的 .hasNext() 正则表达式进行比较时,由于末尾有额外的逗号,它不匹配。
一个解决方案可能是让扫描器对 .hasNext() 和 .next() 方法使用空白标记分隔符,并将正则表达式应用于 println 语句。
while(s.hasNext()) {
Matcher m = wordPattern.matcher(s.next());
if (m.find()) {
System.out.println("word:" + m.group(0))
}
}
scanner 的 hasNext 大部分没用。
扫描器是这样工作的:
- 在相关的任何时间(在任何
next()
/ nextX()
调用,或任何 hasNext
调用,但不包括 nextLine()
,确保扫描器知道 'next token in the queue'。如果还没有,那么就去阅读,从提要中读取另一个标记。这是通过完全忽略要求的内容,而是扫描 end-of-stream、 来完成的或 'delimiter'(默认情况下为 'any whitespace')。到那时为止的所有内容都是下一个标记。
- hasX() 检查行中的下一个标记,returns true 或 false 取决于它是否匹配。与是否还有数据可读无关
- nextLine 忽略了所有这些并且不能很好地与扫描仪中的其他任何东西一起使用。
因此,您正在调用 hasNext,并且 hasNext 忠实地报告:嗯,行中的下一个标记是 bank,
,它与正则表达式不匹配,因此 returns false
.正如文档所说。
解决方案
忘记 hasX,你不需要那些。您也永远不需要 nextLine。如果分隔符不好(即从不调用 nextLine,而是调用 useDelimiter("\r?\n")
和 next()
)并调用 .nextX() 方法,则如果您更改分隔符,则 Scanner 效果最佳。这就是你用它所做的一切。
所以,只需调用 next()
,检查它是否匹配,然后继续。
这是我的解析方法。
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-z 和撇号)。谢谢!
扫描器正在将文本分成“标记”。默认的标记分隔符是空格。当您的程序停止时,当前标记为 bank,
当您将其与您的 .hasNext() 正则表达式进行比较时,由于末尾有额外的逗号,它不匹配。
一个解决方案可能是让扫描器对 .hasNext() 和 .next() 方法使用空白标记分隔符,并将正则表达式应用于 println 语句。
while(s.hasNext()) {
Matcher m = wordPattern.matcher(s.next());
if (m.find()) {
System.out.println("word:" + m.group(0))
}
}
scanner 的 hasNext 大部分没用。
扫描器是这样工作的:
- 在相关的任何时间(在任何
next()
/nextX()
调用,或任何hasNext
调用,但不包括nextLine()
,确保扫描器知道 'next token in the queue'。如果还没有,那么就去阅读,从提要中读取另一个标记。这是通过完全忽略要求的内容,而是扫描 end-of-stream、 来完成的或 'delimiter'(默认情况下为 'any whitespace')。到那时为止的所有内容都是下一个标记。 - hasX() 检查行中的下一个标记,returns true 或 false 取决于它是否匹配。与是否还有数据可读无关
- nextLine 忽略了所有这些并且不能很好地与扫描仪中的其他任何东西一起使用。
因此,您正在调用 hasNext,并且 hasNext 忠实地报告:嗯,行中的下一个标记是 bank,
,它与正则表达式不匹配,因此 returns false
.正如文档所说。
解决方案
忘记 hasX,你不需要那些。您也永远不需要 nextLine。如果分隔符不好(即从不调用 nextLine,而是调用 useDelimiter("\r?\n")
和 next()
)并调用 .nextX() 方法,则如果您更改分隔符,则 Scanner 效果最佳。这就是你用它所做的一切。
所以,只需调用 next()
,检查它是否匹配,然后继续。