【问题标题】:Sending large files Client to Server将大文件客户端发送到服务器
【发布时间】:2014-04-28 13:15:06
【问题描述】:

我正在尝试将文件发送到我的服务器。我让它处理小于 100mb 的文件。否则我的堆用完了。所以我重做了它,但不能真正让它工作。除了读取我卡在 bis.read(buffer) 中的最后一个数据之外,我还开始工作,因为它不知道文件何时结束。所以我尝试发送每个段的长度,以便 bufferedInputStream 知道何时停止读取。

知道有什么问题吗?

发件人代码:

        FileInputStream fis = new FileInputStream(file);
        byte[] buffer = new byte[2048];
        Integer bytesRead = 0;
        BufferedOutputStream bos = new BufferedOutputStream(clientSocket.getOutputStream());
        BufferedInputStream bis = new BufferedInputStream(fis);

        while ((bytesRead = bis.read(buffer)) > 0) {
            objectOutStream.writeObject(bytesRead);
            bos.write(buffer, 0, bytesRead);

        }
        System.out.println("Sucess sending file");

接收方(服务器):

       fileName = request.getFileName();
       int size = (int) request.getSize();

        BufferedInputStream bis = new BufferedInputStream(clientSocket.getInputStream());

        FileOutputStream fos = new FileOutputStream(fileName);
        int totalBytesReceived = 0;
        int blockSize = 0;
        while (totalBytesReceived < size) {
            Object o = ois.readObject();

            if (!(o instanceof Integer)) {
                System.out.println("Something is wrong");
            }
            blockSize = (Integer) o;

            buffer = new byte[blockSize];

            bis.read(buffer);
            totalBytesReceived += blockSize;
            fos.write(buffer, 0, blockSize);
        }
        System.out.println("File succes");

【问题讨论】:

    标签: java sockets client


    【解决方案1】:

    您在服务器端的阅读代码应该与客户端相同。

    // copy from bis to bos, using a buffer.
    for(int len; (len = bis.read(buffer)) > 0) {
        bos.write(buffer, 0, len);
    }
    

    在你想要的客户端

    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filename));
    BufferedOutputStream bos = new BufferedOutputStream(clientSocket.getOutputStream());
    

    在您想要的服务器端。

    BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filename));
    

    完成后你想

    bos.close();
    bis.close();
    

    如果您要使用 ObjectOutputStream(我建议您不要),您只需要使用此流,而不是混合流。

    【讨论】:

    • +1 表示 ObjectOutputStream 注释。我也正要在我的回答中写下这一点。
    【解决方案2】:

    您可以简化代码。当您到达流的末尾时,您将从bis.read() 获得-1。这样您就不需要知道文件的长度。以及flush()close() 服务器和客户端上的流。正如另一张海报所说,不要使用ObjectOutputStreamObjectIntputStream。您将获得似乎会损坏您的数据的序列化标头。

       fileName = request.getFileName();
    
        BufferedInputStream bis = new BufferedInputStream(clientSocket.getInputStream());
    
        FileOutputStream fos = new FileOutputStream(fileName);
        int data = bis.read(); //reads an int
        while (data != -1) {
            fos.write(data);
            data = bis.read();
    
        }
        fos.flush();
        fos.close();
    
        System.out.println("File succes");
    

    【讨论】:

    • bis.read() 读取一个无符号字节。 while(data += -1) 不会编译。 ois 未声明。
    • @PeterLawrey bis.read() 是不正确的。在 Java 中哪里可以得到未签名的任何东西(char 除外)?来自文档:“返回:数据的下一个字节,如果到达流的末尾,则返回 -1。” += 显然是一个错字。 OP 的帖子中留下了 ois 的废话。我会解决的。
    • @PeterLawrey 我不知道你为什么做出无符号字节注释,所以我回去查看文档。 read() 以 int 形式返回 0 到 255 的值,如果到达流的末尾,则返回 -1。函数类似于无符号字节,但不是字节。 write() 接受一个与 read() 返回的匹配的 int。
    • 读取 int 可能意味着它读取 4 个字节,而不是仅读取一个字节,但使用 int,因为有 257 个可能的结果。您可能想知道为什么不使用 short 。我怀疑这是因为 JVM 实际上不支持比int 更窄的堆栈类型(返回值和参数)并且比这更窄的类型实际上使用一个 32 位插槽。
    猜你喜欢
    • 1970-01-01
    • 2013-08-25
    • 2015-05-02
    • 1970-01-01
    • 2016-02-17
    • 2013-05-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多