读取DataInputStream时遭遇EOFException问题求助
问题根源
你的代码出现EOFException的核心原因是读写数据的格式完全不匹配:
- 写入时,所有数据(包括账号数字、余额)都通过
writeUTF()以字符串形式写入文件; - 读取时却试图用
readInt()、readDouble()读取对应类型的二进制数据,这会导致读取解析错误,很快触发文件末尾异常。
另外,read.available()不能可靠判断文件是否还有未读取数据,这个方法仅返回当前输入流中可立即读取的字节数,不能作为循环终止条件。
解决方案
提供两种修复方式,选其一即可:
方案一:修改写入代码,匹配读取的类型
将写入时的字符串转换操作去掉,直接用对应类型的写入方法:
try { Scanner input = new Scanner(new File("accounts.txt")); int index = 0; int accNum = 0; String accName = ""; double balance = 0; String accType = ""; ArrayList<Account> accounts = new ArrayList<>(); while (input.hasNextLine()) { if (index == 0) { accNum = Integer.parseInt(input.nextLine()); index++; } else if (index == 1) { accName = input.nextLine(); index++; } else if (index == 2) { accType = input.nextLine(); index++; } else if (index == 3) { balance = Double.parseDouble(input.nextLine()); accounts.add(new Account(accNum, accName, balance, accType)); index = 0; } } input.close(); try (FileOutputStream accountTxtFile = new FileOutputStream("accounts.bin"); DataOutputStream accountBinFile = new DataOutputStream(accountTxtFile)) { for (Account accountObj : accounts) { accountBinFile.writeInt(accountObj.getAccountNumber()); accountBinFile.writeUTF(accountObj.getAccountHolderName()); accountBinFile.writeUTF(accountObj.getAccountType()); accountBinFile.writeDouble(accountObj.getBalance()); // 验证输出 System.out.println(accountObj.getAccountNumber()); System.out.println(accountObj.getAccountHolderName()); System.out.println(accountObj.getAccountType()); System.out.println(accountObj.getBalance()); } } } catch (IOException e) { e.printStackTrace(); }
同时修改读取代码,用try-catch捕获EOFException作为循环结束标志(替代不可靠的available()):
try (DataInputStream read = new DataInputStream(new FileInputStream("accounts.bin"))) { while (true) { try { int accNum = read.readInt(); String accName = read.readUTF(); String accType = read.readUTF(); double balance = read.readDouble(); System.out.println(accNum + " " + accName + " " + accType + " " + balance); } catch (EOFException e) { // 读取到文件末尾,正常退出 break; } } } catch (IOException e) { System.err.println("文件操作出错"); e.printStackTrace(); }
方案二:修改读取代码,匹配写入的格式
如果不想改动写入逻辑,就统一用readUTF()读取所有数据,再转换为对应类型:
try (DataInputStream read = new DataInputStream(new FileInputStream("accounts.bin"))) { while (true) { try { String accNumStr = read.readUTF(); String accName = read.readUTF(); String accType = read.readUTF(); String balanceStr = read.readUTF(); int accNum = Integer.parseInt(accNumStr); double balance = Double.parseDouble(balanceStr); System.out.println(accNum + " " + accName + " " + accType + " " + balance); } catch (EOFException e) { // 读取到末尾,退出循环 break; } catch (NumberFormatException e) { System.err.println("数据格式转换失败"); e.printStackTrace(); } } } catch (IOException e) { System.err.println("文件操作出错"); e.printStackTrace(); }
额外注意
- 优先使用try-with-resources语法(如上述代码),它会自动关闭流,避免资源泄漏;
- 不要依赖
available()判断文件是否读完,这种方式在网络流或缓冲流场景下完全不可靠,捕获EOFException是更稳妥的方式。
内容的提问来源于stack exchange,提问作者gangrx
相关产品推荐
相关产品推荐

