0

好的....尝试自己学习java,有一段时间遇到了麻烦。我正在尝试使用套接字和缓冲的输入和输出流通过网络传输一个大文件。不管我尝试传输什么大小的文件。希望我正确发布了我的代码,我知道这段代码可能存在很多问题,尽管它编译并运行正常,但在客户端和服务器进入 while 循环的第二次我得到一个 IndexOutOfBoundsException,服务器在第一次 bis.read 期间得到它(buf,0,len) 并且客户端在 while(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");
    }
}
4

3 回答 3

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但您从不使用它。

于 2012-04-19T00:45:33.290 回答
0

您将流包装两次,一次 asdis和一次 as bis。这意味着 dis 没有被缓冲,但是当你关闭它时,你关闭了底层流。

我建议你只包装使用

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

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

@fgb 注释:您在发送大小上正确使用了长度 read() 但在接收大小上忽略了它(具有讽刺意味的是,您通常在读取文件时获得所需的大小,但在读取套接字时却没有那么多)

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

于 2012-04-19T05:37:30.733 回答
0

您正在使用固定缓冲区大小。尝试这个:

byte[] mybytearray = new byte[(int) myFile.length()];
于 2013-06-25T13:54:33.310 回答