通过套接字发送大文件时出错

时间:2013-11-28 22:46:55

标签: java file sockets send

我正在尝试通过套接字发送大文件。该程序适用于小文件(如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");
        }
    }

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

3 个答案:

答案 0 :(得分:3)

这是不正确的:

        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或典型操作系统无法保证的行为。

答案 1 :(得分:0)

您可能遇到问题,例如这里。

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

此处读取会为您提供实际读取的字节数。 在下一行,你应该只写出你读过的字节数。

换句话说,你不能指望文件的大小 你读的是你的缓冲区大小的倍数。

检查您的服务器代码是否存在同样的问题。

答案 2 :(得分:0)

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

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

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

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