0

わかりました.... Javaを独学で学ぼうとしているのですが、しばらくこれに悩まされていました。ソケットとバッファリングされた入出力ストリームを使用して、ネットワーク経由で大きなファイルを転送しようとしています。転送しようとするファイルのサイズは関係ありません。コードを正しく投稿したことを願っています。このコードにはおそらく多くの問題があることを知っていますが、コンパイルして正常に実行されますが、クライアントとサーバーが while ループに入ると 2 番目に 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

固定バッファ サイズを使用しています。これを試して:

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

ストリームを 2 回ラップしていdisますbis。これは、dis がバッファリングされていないことを意味しますが、それを閉じると、基になるストリームが閉じられます。

ラップのみを使用することをお勧めします

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

効率的なバッファ サイズが必要な場合は、2 の累乗、つまり 4092 ではなく 4096 をお勧めします。

@fgb メモ: 送信サイズでは長さ read() を正しく使用しますが、受信サイズでは無視します (皮肉なことに、通常、ファイルを読み取るときに必要なサイズが得られますが、ソケットを読み取るときはそれほど多くはありません)

IOUtils.copy() のように、両方の状況で機能する 1 つの共通の InputStream から OutputStream へのコピー メソッドを使用することを検討してください。

于 2012-04-19T05:37:30.733 に答える