PrintWriter异常求助:国际象棋游戏存档功能无法正常工作
排查APCS国际象棋存档类SaveListener的输出异常问题
我在为APCS期末项目编写国际象棋游戏的存档类SaveListener时碰到了个头疼的问题:这个类本该完整保存整个棋局的状态,但实际运行后,生成的文件里居然只有ro00\n这一行内容。我试过更换Writer类型、添加/移除flush()操作等多种写法,当前版本已经是最接近正常的了,附上相关代码和期望结果,麻烦帮忙排查下问题!
问题代码片段
class SaveListener implements ActionListener { String temp; public void actionPerformed(ActionEvent e) { System.out.println(">saveInitiated"); try { write = new PrintWriter(new OutputStreamWriter( new FileOutputStream("Board.txt"), "utf-8")); /*write = new PrintWriter(new File("Board.txt"), "UTF-8");*/ for (int y = 0; y < 8; y ++) { for (int x = 0; x < 8; x++) { System.out.printf(">>y:%d,x:%d\n", y, x); if (Board[y][x] != null) { temp = Board[y][x].getType(); switch (temp) { case "pawn": write.print("pa"); break; case "rook": write.print("ro"); break; case "knight": write.print("kn"); break; case "bishop": write.print("bi"); break; case "queen": write.print("qu"); break; case "king": write.print("ki"); break; } write.flush(); write.print(y); write.flush(); write.print(x + "\n"); write.flush(); } else { write.print("nu\n"); } write.close(); // 这里就是问题根源! } } } catch (FileNotFoundException e1) { System.out.println(">>FileNotFound!"); } catch (UnsupportedEncodingException e1) { System.out.println(">>unsupportedEncodingException"); } System.out.println(">saveConcluded"); } }
正常参考代码(可正常完整存档)
if (save) { PrintWriter write = new PrintWriter("Board.txt", "UTF-8"); for (int y = 0; y < board.length; y++) { for (int x = 0; x < board[y].length; x++) { write.print(board[y][x] + " "); } } write.close(); // 所有写入完成后才关闭流 System.out.println("Saved"); save = false; }
期望生成的文件内容
(空格仅为可读性添加,实际无空格)ro00\n kn01\n bi02\n ki03\n qu04\n bi05\n kn06\n ro07\n pa00\n pa01\n pa02\n pa03\n pa04\n pa05\n pa06\n pa07\n nu\n nu\n ...(中间空行省略)... pa60\n pa61\n ... ro77
问题根源分析
你代码里最致命的错误是在最内层的x循环里就调用了write.close()!这意味着第一次循环(y=0,x=0)执行完之后,输出流就被直接关闭了,后面所有的写入操作都会因为流已关闭而失效,所以最终文件里只会保留第一个棋子的记录ro00\n。
另外还有个小细节:你每次写入后都调用flush()其实没必要,PrintWriter本身带有缓冲机制,在关闭流的时候会自动把缓冲区的内容写入文件,频繁调用flush()反而会降低性能。
修复后的代码
class SaveListener implements ActionListener { public void actionPerformed(ActionEvent e) { System.out.println(">saveInitiated"); PrintWriter write = null; // 提前声明变量 try { write = new PrintWriter(new OutputStreamWriter( new FileOutputStream("Board.txt"), "utf-8")); for (int y = 0; y < 8; y ++) { for (int x = 0; x < 8; x++) { System.out.printf(">>y:%d,x:%d\n", y, x); if (Board[y][x] != null) { String temp = Board[y][x].getType(); // 缩小变量作用域 switch (temp) { case "pawn": write.print("pa"); break; case "rook": write.print("ro"); break; case "knight": write.print("kn"); break; case "bishop": write.print("bi"); break; case "queen": write.print("qu"); break; case "king": write.print("ki"); break; } write.print(y); write.print(x + "\n"); } else { write.print("nu\n"); } } } // 所有写入操作完成后再关闭流,自动flush缓冲区 if (write != null) { write.close(); } } catch (FileNotFoundException e1) { System.out.println(">>FileNotFound!"); } catch (UnsupportedEncodingException e1) { System.out.println(">>unsupportedEncodingException"); } finally { // 额外保险:确保流被关闭 if (write != null && !write.checkError()) { write.close(); } } System.out.println(">saveConcluded"); } }
验证建议
运行修改后的代码后,你可以:
- 查看控制台的
>>y:x日志,确认它打印了所有64个格子的坐标(0-7的y和x组合) - 打开生成的
Board.txt文件,检查内容是否和你期望的完整棋局记录一致
内容的提问来源于stack exchange,提问作者Natan Bagley
相关产品推荐
相关产品推荐

