
java 的 scanner 类不支持回退或重置到文件开头,解决方法是用新 scanner 实例重新打开同一文件,这是最简洁、可靠且符合初学者认知的方式。
在使用 Scanner 逐行或逐词读取文本文件时,一个常见误区是认为存在类似 reset() 或 rewind() 的方法可将读取位置返回文件起始处。但事实上,Scanner.reset() 并不会重置底层输入流的位置——它仅重置分隔符(delimiter)和区域设置(locale)等扫描配置,对文件指针毫无影响。因此,调用 reader.reset() 后继续调用 hasNext() 或 nextInt() 仍会返回 false,因为文件已读至末尾。
✅ 正确做法:丢弃旧 Scanner,新建一个指向同一 File 对象的新 Scanner
这既符合 Java I/O 设计原则,又无需额外依赖(如 RandomAccessFile 或 BufferedReader.mark()),代码清晰、安全且易于理解:
File f = new File("Test Data.txt");
Scanner reader = new Scanner(f);
// 第一遍:统计整数个数
int counter = 0;
while (reader.hasNextInt()) { // 推荐用 hasNextInt() 替代 hasNext(),更精准
reader.nextInt();
counter++;
}
System.out.println("YOU HAVE " + counter + " DATA POINTS IN THE FILE");
// ✅ 关键步骤:关闭旧 Scanner,并用同一文件创建新 Scanner
reader.close();
reader = new Scanner(f); // ← 重新打开,自动从文件开头开始读取
// 第二遍:读取并存入数组
int[] myNumbers = new int[counter];
for (int i = 0; i < counter; i++) {
if (reader.hasNextInt()) {
myNumbers[i] = reader.nextInt();
System.out.println("Index " + i + ": " + myNumbers[i]);
}
}
reader.close();? 注意事项:
- 务必先调用 reader.close() 再创建新 Scanner:避免资源泄漏(尤其是文件句柄),也防止某些系统下因文件被占用导致 FileNotFoundException。
- 使用 hasNextInt() 而非 hasNext() 更健壮:避免因空行、注释或非数字字符导致 InputMismatchException。
- 不要尝试 reader.useDelimiter("\\A") 或 mark()/reset() 等技巧:Scanner 包装的 FileInputStream 默认不支持标记(markSupported() 返回 false),强行调用会抛出 IOException。
? 总结:对于初学者项目中「必须使用定长数组」且「不可用 ArrayList」的约束,两次扫描 + 新建 Scanner 是标准、推荐且最易教学的解法。它逻辑直白、无副作用、完全兼容 Java SE 7+,也是官方文档与主流教材所倡导的实践方式。










