Java通过Streams和Sockets传输二进制文件后无法打开求助
解决Java Socket传输二进制文件后无法打开的问题
我帮你排查了代码里的问题,主要有几个关键错误导致文件传输后损坏,下面是修正方案和详细说明:
问题分析
- 服务器端输入流错误:你把
Socket.getInputStream()强转成FileInputStream,这完全是错误的——Socket的输入流和文件输入流是不同的实现,强转后根本读不到客户端发送的正确数据。 - 未循环读取完整数据:
read(byte[])方法不会保证一次读完所有字节,尤其是大文件(比如你的MP4),只调用一次会导致部分数据丢失。 - 流未正确关闭/刷新:输出流没有彻底flush和关闭,缓冲区里的剩余数据可能没写入文件。
- 错误的文件长度依赖:服务器端用本地文件的长度创建字节数组,但实际应该接收客户端发送的文件,这个本地文件变量完全多余且误导。
修正后的服务器端代码
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class FileServer { public static void main(String[] args) throws IOException { ServerSocket servsock = new ServerSocket(4567); System.out.println("Waiting for connection"); Socket sock = servsock.accept(); System.out.println("Connected"); // 正确使用Socket的输入流,不要强转成FileInputStream BufferedInputStream bis = new BufferedInputStream(sock.getInputStream()); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("C:/Users/rp00491429/Downloads/dfgd.mp4")); byte[] buffer = new byte[8192]; // 用固定大小的缓冲区,避免大文件占用过多内存 int bytesRead; // 循环读取直到输入流结束(返回-1) while ((bytesRead = bis.read(buffer)) != -1) { bos.write(buffer, 0, bytesRead); // 只写入实际读取到的字节数 } // 确保缓冲区数据全部写入文件,然后关闭所有流 bos.flush(); bos.close(); bis.close(); sock.close(); servsock.close(); System.out.println("File received successfully"); } }
修正后的客户端代码
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.net.Socket; public class FileClient { public static void main(String[] ar) { try (Socket socket = new Socket("localhost", 4567); BufferedInputStream bis = new BufferedInputStream(new FileInputStream("C:\\Users\\rp00491429\\Downloads\\greatdeepak.mp4")); BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream())) { byte[] buffer = new byte[8192]; int bytesRead; // 循环读取本地文件并发送 while ((bytesRead = bis.read(buffer)) != -1) { bos.write(buffer, 0, bytesRead); } bos.flush(); // 确保所有数据发送完毕 System.out.println("File sent successfully"); } catch (Exception e) { e.printStackTrace(); // 不要吞掉异常,方便排查问题 } } }
关键修改点说明
- 流的正确使用:服务器端直接用Socket的输入流构建BufferedInputStream,不要再强转;客户端和服务器都使用缓冲流提升效率。
- 循环读取写入:用
while循环处理read()的返回值,确保所有字节都被读取和写入,避免数据丢失。 - 资源自动管理:客户端使用try-with-resources语法,自动关闭流和Socket,避免资源泄漏;服务器端也手动关闭所有资源。
- 缓冲区大小:使用8192字节的缓冲区,既保证传输效率,又不会占用过多内存,适合大文件传输。
- 异常处理:客户端不再吞掉异常,打印异常信息方便调试。
这样修改后,传输的MP4文件就能正常打开了。
内容的提问来源于stack exchange,提问作者Ramana
相关产品推荐
相关产品推荐

