【问题标题】:Error while sending large files through socket通过套接字发送大文件时出错
【发布时间】:2013-12-15 01:31:45
【问题描述】:

我正在尝试通过套接字发送大文件。该程序适用于小文件(例如 html 页面或 pdf),但是当我发送超过 3/4 mb 的文件时,输出总是损坏(用文本编辑器查看它,我注意到最后几行总是丢失)。

这是服务器的代码:

BufferedInputStream in = null;
    FileOutputStream fout = null;
    try {
        server = new ServerSocket(port);

        sock = server.accept();
        in = new BufferedInputStream(sock.getInputStream());

        setPerc(0);

        received = 0;

        int incByte = -1;
        fout = new FileOutputStream(path+name, true);
        long size = length;
        do{
            int buffSize;
            if(size >= 4096){
                buffSize = 4096;
            }else{
                buffSize = 1;
            }
            byte[] o = new byte[buffSize];
            incByte = in.read(o, 0, buffSize);
            fout.write(o);

            received+=buffSize;
            setPerc(calcPerc(received, length));
            size -= buffSize;
            //d("BYTE LETTI => "+incByte);
        }while(size > 0);
        server.close();
    } catch (IOException e) {
        e("Errore nella ricezione file: "+e);
    }finally{
        try {
            fout.flush();
            fout.close();
            in.close();
        } catch (IOException e) {
            e("ERRORE INCOMINGFILE");
        }
    }
    pr.release(port);

这是客户端的代码:

FileInputStream fin = null;
    BufferedOutputStream out = null;
    try {
        sock = new Socket(host, port);

        fin = new FileInputStream(file);
        out = new BufferedOutputStream(sock.getOutputStream());

        long size = file.length();
        int read = -1;
        do{
            int buffSize = 0;
            if(size >= 4096){
                buffSize = 4096;
            }else{
                buffSize = (int)size;
            }

            byte[] o = new byte[buffSize];
            for(int i = 0; i<o.length;i++){
                o[i] = (byte)0;
            }
            read = fin.read(o, 0, buffSize);
            out.write(o);
            size -= buffSize;
            //d("BYTE LETTI DAL FILE => "+read);
        }while(size > 0);
    } catch (UnknownHostException e) {
    } catch (IOException e) {
        d("ERRORE NELL'INVIO DEL FILE: "+e);
        e.printStackTrace();
    }finally{
        try {
            out.flush();
            out.close();
            fin.close();
        } catch (IOException e) {
            d("Errore nella chiusura dei socket invio");
        }
    }

我认为这与缓冲区大小有关,但我无法弄清楚这里出了什么问题。

【问题讨论】:

  • 永远不要依赖File.length() 提供的文件大小,而是继续阅读直到完成。 File.length() 应该用来说明它可能有多大。

标签: java file sockets send


【解决方案1】:

Java中复制流的正确方法如下:

while ((count = in.read(buffer)) > 0)
{
    out.write(buffer, 0, count);
}

其中countint,buffer 是长度> 0 的byte[] 数组,通常为8k。您不需要在循环内分配字节数组,也不需要特定大小的字节数组。具体来说,分配与文件一样大的缓冲区完全是浪费空间;它仅适用于 Integer.MAX_VALUE 字节的文件,并且无法扩展。

你确实需要保存'read()'返回的计数,并在上面显示的'write()'方法中使用它。

【讨论】:

    【解决方案2】:

    这是不正确的:

            byte[] o = new byte[buffSize];
            incByte = in.read(o, 0, buffSize);
            fout.write(o);
    

    您正在读取最多 buffSize 字节,然后写入准确 buffSize 字节。

    你也在另一端做同样的事情。

    从文件1 读取时,您也许可以避免这种情况,但是当您从套接字读取时,read 可能会为您提供部分填充的缓冲区,特别是如果写入端不能总是领先于读取端,因为您正在通过大量传输来锤击网络。

    正确的做法是:

            incByte = in.read(o, 0, buffSize);
            fout.write(o, 0, incByte);
    

    1 - 据观察,当您从本地文件读取时,read 调用通常会为您提供您请求的所有字节(取决于文件大小等)。因此,如果您将buffSize 设置为文件的长度,则此代码在从本地文件读取时可能会起作用。但这样做是个坏主意,因为您所依赖的行为不受 Java 或典型操作系统的保证。

    【讨论】:

      【解决方案3】:

      您可能有问题,例如在这里。

      read = fin.read(o, 0, buffSize);
      out.write(o);
      

      这里 read 为您提供您实际刚刚读取的字节数。 在下一行,你应该只写出你读过的字节数。

      换句话说,你不能期望文件的大小 您正在读取的是缓冲区大小的倍数。

      也针对相同的问题检查您的服务器代码。

      【讨论】:

        猜你喜欢
        • 2015-07-24
        • 2012-07-12
        • 2019-11-19
        • 1970-01-01
        • 2017-03-14
        • 2011-02-24
        • 2012-01-30
        相关资源
        最近更新 更多