假设以下代码:
String example = " sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode\n" +
" 0: 00000000:04D2 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 15662 1 ffff8800baf1c780 100 0 0 10 0\n" +
" 1: 00000000:04D2 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 15662 1 ffff8800baf1c780 100 0 0 10 0";
Scanner scanner = new Scanner(example);
scanner.useRadix(16).useDelimiter("[\\s:]+");
while (scanner.hasNextLine()) {
scanner.nextLine(); // skip header on first iteration, which is not needed
int slot = scanner.nextInt();
System.out.println(slot);
}
我基本上读取除标题之外的每一行的第一个整数。我期待看到以下输出:
0
1
但抛出异常:
java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1485)
at java.util.Scanner.nextInt(Scanner.java:2117)
at java.util.Scanner.nextInt(Scanner.java:2076)
问题是为什么Scanner.hasNextLine()
会在最后一行返回true
,显然流中没有新行?
答案 0 :(得分:0)
这在输入结束时发生。您解析1
,它会离开它后面的空格。那么你的循环条件仍然是正确的(有可用的行),所以你读取了这一行,它留在你的字符串的最后。然后,在没有检查的情况下,您尝试读取int。所以它失败了。你需要检查是否有可用的int,因为在最后一行,没有。
这是一个版本,检查是否有可用的int,并显示您正在跳过的内容,这应该会让事情变得更清晰(live copy):
String example = " sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode\n" +
" 0: 00000000:04D2 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 15662 1 ffff8800baf1c780 100 0 0 10 0\n" +
" 1: 00000000:04D2 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 15662 1 ffff8800baf1c780 100 0 0 10 0";
Scanner scanner = new Scanner(example);
scanner.useRadix(16).useDelimiter("[\\s:]+");
Set<Integer> result = new HashSet<>();
scanner.next();
while (scanner.hasNextLine()) {
String skipped = scanner.nextLine();
System.out.println("Skipped: " + skipped); // skip header on first iteration and also skips remainder of previous line after we read the int
if (scanner.hasNextInt()) {
int slot = scanner.nextInt();
System.out.println(slot);
} else {
System.out.println("No int avaialble");
}
}
System.out.println("Done");
我已经为跳过的内容添加了System.out.println
,但实际上您要做的就是在调试器中逐步执行此操作。
这是它输出的内容:
Skipped: local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode 0 Skipped: : 00000000:04D2 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 15662 1 ffff8800baf1c780 100 0 0 10 0 1 Skipped: : 00000000:04D2 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 15662 1 ffff8800baf1c780 100 0 0 10 0 No int avaialble Done
现在,上面的内容有点复杂,因为您在一个循环中读取了部分行(开头的int)但是在开头读取了行的其余部分(int之后的部分)下一个循环。理想情况下,您可以在同一个循环(live copy)中清理它们:
String example = " sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode\n" +
" 0: 00000000:04D2 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 15662 1 ffff8800baf1c780 100 0 0 10 0\n" +
" 1: 00000000:04D2 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 15662 1 ffff8800baf1c780 100 0 0 10 0";
Scanner scanner = new Scanner(example);
scanner.useRadix(16).useDelimiter("[\\s:]+");
Set<Integer> result = new HashSet<>();
scanner.next();
if (scanner.hasNextLine()) {
// Skip the headers
scanner.nextLine();
}
// Process records
while (scanner.hasNextLine()) {
// The first int
if (scanner.hasNextInt()) {
int slot = scanner.nextInt();
System.out.println(slot);
// Read anything else you want from that line, until
// you have only the newline left (or any trailing characters
// you don't want to process and then the newline)
}
// Clear the newline
scanner.nextLine();
}
System.out.println("Done");
输出:
0 1 Done