You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

客户端用BufferedReader读取字节写入文件出现数据不符问题

问题分析与解决方案

嘿,这个问题我一眼就看出核心问题啦——你在处理二进制文件传输的时候误用了字符流,这直接导致原始字节被破坏,出现了错误的内容。咱们一步步拆解问题,再给你修正方案:

问题1:用字符流处理二进制数据是致命错误

你把InputStream转成了BufferedReader(字符流),然后用read()读取单个字符再转成字节写文件。但字符流会把字节按照默认字符编码(比如UTF-8)解码成字符,再编码回字节,这个过程会改变原始二进制数据的结构——比如一些字节序列不是合法的字符,会被替换成占位符(比如�),或者多字节字符被拆分/合并,直接导致文件内容错乱。

问题2:br.ready()不能用来判断流是否结束

ready()方法只是判断当前是否有可读取的字符,不代表整个流已经读完。如果网络传输有延迟,或者数据分批次到达,ready()会提前返回false,导致你只读取了部分数据,剩下的字节没被写入。


修正后的代码方案

直接使用字节流来读写,完全绕过字符编码的问题,同时用正确的方式判断流结束:

InputStream is = clientSocket.getInputStream();
// 注意Java里路径反斜杠要转义,或者用正斜杠
FileOutputStream fos = new FileOutputStream("./Recibido/" + recurso);

byte[] buffer = new byte[4096]; // 用缓冲区提高读写效率
int bytesRead;
// 当read()返回-1时,代表流已经读完
while ((bytesRead = is.read(buffer)) != -1) {
    fos.write(buffer, 0, bytesRead); // 只写入实际读取到的字节数
}

// 关闭资源,最好用try-with-resources自动关闭
fos.close();
is.close();

额外优化建议

  • 使用try-with-resources自动管理资源:避免忘记关闭流导致资源泄漏,代码更简洁:
try (InputStream is = clientSocket.getInputStream();
     FileOutputStream fos = new FileOutputStream("./Recibido/" + recurso)) {
    byte[] buffer = new byte[4096];
    int bytesRead;
    while ((bytesRead = is.read(buffer)) != -1) {
        fos.write(buffer, 0, bytesRead);
    }
} catch (IOException e) {
    e.printStackTrace();
}
  • 检查文件路径合法性:确保./Recibido目录存在,否则会抛出FileNotFoundException,可以提前用new File("./Recibido").mkdirs()创建目录。

这样修改后,就能准确读取和写入原始字节,不会再出现内容错乱的问题啦~

内容的提问来源于stack exchange,提问作者Dgrm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:12:15