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

Java通过Streams和Sockets传输二进制文件后无法打开求助

解决Java Socket传输二进制文件后无法打开的问题

我帮你排查了代码里的问题,主要有几个关键错误导致文件传输后损坏,下面是修正方案和详细说明:

问题分析

  1. 服务器端输入流错误:你把Socket.getInputStream()强转成FileInputStream,这完全是错误的——Socket的输入流和文件输入流是不同的实现,强转后根本读不到客户端发送的正确数据。
  2. 未循环读取完整数据:read(byte[])方法不会保证一次读完所有字节,尤其是大文件(比如你的MP4),只调用一次会导致部分数据丢失。
  3. 流未正确关闭/刷新:输出流没有彻底flush和关闭,缓冲区里的剩余数据可能没写入文件。
  4. 错误的文件长度依赖:服务器端用本地文件的长度创建字节数组,但实际应该接收客户端发送的文件,这个本地文件变量完全多余且误导。

修正后的服务器端代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:44:41