Java套接字传输,缓冲输入和输出

时间:2012-04-19 00:27:36

标签: java

好的....试着自己学习java,这个问题已经有一段时间了。我正在尝试使用套接字和缓冲的输入和输出流在网络上传输大文件。无论我尝试传输什么尺寸的文件。希望我正确地发布了我的代码,我知道这个代码可能有很多问题,虽然它编译并运行正常,我得到一个IndexOutOfBoundsException,第二个客户端和服务器进入while循环,服务器在第一个bis.read期间得到它(buf,0,len)和客户端在此期间得到它(off = fis.read(buf,0,len).....任何帮助将不胜感激

//Server Receive code receive method and main for testing
    public File receive(Socket socket) throws IOException{

        //temporarily hard coded filename
        File file = new File("C:\\users\\tom5\\desktop\\sales\\input.dat");
        DataInputStream dis = new DataInputStream(socket.getInputStream());
        FileOutputStream fos = new FileOutputStream(file);
        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        //reads file length from datainputstream
        int len = dis.readInt();
        dis.close();
        int bytesRead=0;
        //create buffer
        byte[]buf = new byte[4092];
        int off = 0;

        //read from BufferedInputStream and write to FileOutputStream?
        while(bytesRead < len) {
            bis.read(buf,0,len);
            fos.write(buf,0,len);
            bytesRead++;
        }
        fos.close();
        bis.close();
        return file;
    }
    public static void main(String[]args) throws IOException{
        Server server = new Server();
        Socket socket =server.accept();
        File file = server.receive(socket);
    }
}

//Client sending code

    public void send(Socket socket,File file) throws IOException{
        FileInputStream fis = new FileInputStream(file);
        DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        int len = (int)file.length();
        dos.writeInt(len);
        dos.flush();
        dos.close();
        System.out.println(file.length());

        byte[]buf = new byte[4092];
        int off= 0;
        while((off = fis.read(buf,0,len)) != -1  ){
            bos.write(buf,0,len);       
        }
    }

    public static void main(String[]args) throws UnknownHostException, IOException{
        Client client = new Client();
        Socket socket =client.connect("localhost",1055);
        File file = new File("C:\\users\\tom5\\desktop\\movie.avi");
    }
}

3 个答案:

答案 0 :(得分:3)

while(bytesRead < len) {
    bis.read(buf,0,len);
    fos.write(buf,0,len);
    bytesRead++;
}

您尝试将len个字节读入buf,这大于其长度,并且每次将字节递增1,即使read可以读取多个字节。它应该更像是:

while(bytesRead < len) {
    int n = bis.read(buf);
    fos.write(buf, 0, n);
    bytesRead += n;
}

或者如果在您不想阅读的文件之后可能有额外的字节:

while(bytesRead < len) {
    int n = bis.read(buf, 0, Math.min(buf.length, len - bytesRead));
    fos.write(buf, 0, n);
    bytesRead += n;
}

write方法中存在类似的问题。您将返回值存储在off中,但您永远不会使用它。

答案 1 :(得分:0)

您要将流包裹两次,一次为dis,一次为bis。这意味着dis不会被缓冲,但是当你关闭它时,你会关闭底层流。

我建议你只使用

DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));

如果你想要一个有效的缓冲区大小,我建议你2的幂,即4096而不是4092.

@fgb注意事项:你正确使用发送大小上的read()长度但是在接收大小上忽略它(具有讽刺意味的是你通常得到你在阅读文件时要求的大小,但不是那么多读一个插座)

考虑将一个常见的InputStream用于OutputStream复制方法,该方法适用于两种情况,例如:比如IOUtils.copy()。

答案 2 :(得分:0)

您使用的是固定缓冲区大小。试试这个:

byte[] mybytearray = new byte[(int) myFile.length()];