5

ソケットを使用して Java でプログラムを作成しています。コマンドをクライアントに送信したり、クライアントからサーバーに送信したりできます。コマンドを読むには、BufferedReader. それらを書き込むには、 aしかし、今はそのソケットPrintWriterを介してファイルを転送したい(単純に2番目の接続を作成するのではなく) . まず、ファイルに含まれるバイト数を出力ストリームに書き込みます。たとえば、40000 バイトです。したがって、ソケットを介して番号を書き込みますが、接続の反対側は.
4000078

だから私は考えていました:(を呼び出すことによってBufferedReader単なる行以上のものを読み取り、その方法でファイルデータからいくつかのバイトを失います。からのバッファにあるためです。 したがって、数値は送信したいファイルのバイトです。 readLine()BufferedReader
78

この考え方は正しいのか、そうでないのか。もしそうなら、この問題を解決する方法。
うまく説明できたと思います。


これが私のコードですが、デフォルトの言語はオランダ語です。そのため、一部の変数名は奇妙に聞こえる場合があります。

public void flushStreamToStream(InputStream is, OutputStream os, boolean closeIn, boolean closeOut) throws IOException {
    byte[] buffer = new byte[BUFFERSIZE];
    int bytesRead;
    if ((!closeOut) && closeIn) { // To Socket from File
        action = "Upload";
        os.write(is.available()); // Here I write 400000
        max = is.available();
        System.out.println("Bytes to send: " + max);
        while ((bytesRead = is.read(buffer)) != -1) {
            startTiming(); // Two lines to compute the speed
            os.write(buffer, 0, bytesRead);
            stopTiming(); // Speed compution
            process += bytesRead;
        }
        os.flush();
        is.close();
        return;
    }
    if ((!closeIn) && closeOut) { // To File from Socket
        action = "Download";
        int bytesToRead = -1;
        bytesToRead = is.read(); // Here he reads 78.
        System.out.println("Bytes to read: " + bytesToRead);
        max = bytesToRead;
        int nextBufferSize;
        while ((nextBufferSize = Math.min(BUFFERSIZE, bytesToRead)) > 0) {
            startTiming();
            bytesRead = is.read(buffer, 0, nextBufferSize);
            bytesToRead -= bytesRead;
            process += nextBufferSize;
            os.write(buffer, 0, bytesRead);
            stopTiming();
        }
        os.flush();
        os.close();
        return;
    }
    throw new IllegalArgumentException("The only two boolean combinations are: closeOut == false && closeIn == true AND closeOut == true && closeIn == false");
}

解決策は次のとおりです。James の
提案のおかげで、 laginimaineb anwser は解決策の一部だった
と思います。

コマンドを読みます。

DataInputStream in = new DataInputStream(is); // Originally a BufferedReader
// Read the request line
String str;
while ((str = in.readLine()) != null) {
    if (str.trim().equals("")) {
       continue;
    }
    handleSocketInput(str);
}

次に、flushStreamToStream:

public void flushStreamToStream(InputStream is, OutputStream os, boolean closeIn, boolean closeOut) throws IOException {
    byte[] buffer = new byte[BUFFERSIZE];
    int bytesRead;
    if ((!closeOut) && closeIn) { // To Socket from File
        action = "Upload";
        DataOutputStream dos = new DataOutputStream(os);
        dos.writeInt(is.available());

        max = is.available();
        System.out.println("Bytes to send: " + max);
        while ((bytesRead = is.read(buffer)) != -1) {
            startTiming();
            dos.write(buffer, 0, bytesRead);
            stopTiming();
            process += bytesRead;
        }
        os.flush();
        is.close();
        return;
    }
    if ((!closeIn) && closeOut) { // To File from Socket
        action = "Download";
        DataInputStream dis = new DataInputStream(is);
        int bytesToRead = dis.readInt();
        System.out.println("Bytes to read: " + bytesToRead);
        max = bytesToRead;
        int nextBufferSize;
        while ((nextBufferSize = Math.min(BUFFERSIZE, bytesToRead)) > 0) {
            startTiming();
            bytesRead = is.read(buffer, 0, nextBufferSize);
            bytesToRead -= bytesRead;
            process += nextBufferSize;
            os.write(buffer, 0, bytesRead);
            stopTiming();
        }
        os.flush();
        os.close();
        return;
    }
    throw new IllegalArgumentException("The only two boolean combinations are: closeOut == false && closeIn == true AND closeOut == true && closeIn == false");
}

マーティン。

4

4 に答える 4

4

私はあなたの説明に従ったかどうかわかりません。

ただし、はい。BufferedReaderが実際に読み取る量を実際に制御することはできません。このようなリーダーのポイントは、必要に応じて基になるリソースのチャンクを楽観的に読み取り、バッファーを補充することです。したがって、最初にを呼び出すとreadLine、その内部バッファには要求を処理するのに十分なものがないことがわかり、基になるソースからバッファにどのように感じても、多くのバイトを読み取ります。あなたはちょうどその時求めました。バッファにデータが入力されると、バッファされたコンテンツから行が返されます。

したがって、入力ストリームをBufferedReaderでラップした後は、必ず同じバッファリーダーを介してそのストリームのみを読み取る必要があります。そうしないと、データが失われることになります(一部のバイトが消費され、BufferedReaderのキャッシュに保存されて提供されるのを待っているため)。

于 2009-12-02T17:12:30.460 に答える
1

DataInputStream は、おそらく使用したいものです。また、一般的に役に立たないため、 available() メソッドを使用しないでください。

于 2009-12-02T19:29:35.120 に答える
0

ここでのワイルドな刺し傷-40000はバイナリで1001110001000000です。ここで、最初の7ビットは1001110、つまり78です。つまり、2バイトの情報を書き込んでいますが、7ビットを読み取っています。

于 2009-12-02T17:12:46.030 に答える
0

BufferedReaderは、基になる入力ストリームからの読み取りが1つだけであると想定します。

目的は、基になるストリームからの読み取りの数を最小限に抑えることです(非常に深く委任できるため、コストがかかります)。そのために、バッファを保持します。バッファは、基になるストリームへの1回の呼び出しで、可能な限り多くのバイトを読み込むことで埋められます。

そうです、あなたの診断は正確です。

于 2009-12-02T17:15:30.483 に答える