Java Scanner类hasNext()方法异常咨询:写入文件后仍返回false
这不是Scanner的BUG,是缓存机制导致的“错觉”
嘿,我完全懂你碰到的这个问题!之前帮朋友排查过类似的场景,一开始也以为是Scanner出问题了,后来才搞清楚是它的内部缓存机制在起作用。
问题根源
当你第一次创建Scanner并调用hasNext()读取空文件时,Scanner会尝试从文件输入流中读取数据,发现已经到了文件末尾(EOF),于是会标记这个输入流为“已结束”,同时把这个状态缓存起来。之后你向文件写入新内容,但Scanner并不会主动去刷新这个缓存或者重新检查输入流的状态——它还以为自己已经读到文件结尾了,所以再次调用hasNext()时依然返回false。
至于你说移除if(hasNext())判断后程序能正常运行,大概率是因为你直接调用读取方法(比如nextLine())时,代码的执行顺序隐含了重新获取文件输入流的操作?或者可能你在写入后无意中重新创建了Scanner实例?如果是同一个Scanner实例,直接调用读取方法其实会抛出NoSuchElementException,这点要留意。
解决方案
要解决这个问题,核心是让Scanner重新读取更新后的文件内容,最直接的方式就是:
- 在写入文件完成后,关闭原来的Scanner实例,然后创建一个新的Scanner来读取文件。
给你一个修正后的代码示例:
public static void main(String[] args) throws Exception { File file = new File("file.txt"); // 第一次检查空文件 Scanner scanner = new Scanner(file); System.out.println("空文件时hasNext()结果:" + scanner.hasNext()); // 输出false scanner.close(); // 一定要关闭旧的Scanner // 向文件追加内容(用try-with-resources自动关流) try (FileWriter fw = new FileWriter(file, true); PrintWriter pw = new PrintWriter(fw)) { pw.println("我是新增的内容"); } // 重新创建Scanner读取更新后的文件 Scanner newScanner = new Scanner(file); System.out.println("写入后hasNext()结果:" + newScanner.hasNext()); // 输出true if (newScanner.hasNext()) { System.out.println("读取到的内容:" + newScanner.nextLine()); // 输出"我是新增的内容" } newScanner.close(); }
额外提醒
如果你的场景需要实时监测文件内容变化(比如日志文件),那单纯的Scanner就不够用了,可以考虑使用Java自带的WatchService来监听文件的修改事件,当文件发生变化时再重新创建Scanner读取。不过如果只是单次写入后读取,上面的方案完全足够。
内容的提问来源于stack exchange,提问作者Safar Safarli
相关产品推荐
相关产品推荐

