0

システムの1つで奇妙なエラーが発生し、説明できません。私たちのシステムでは、バックエンドが大きなTSV出力ファイルを生成しており、次のコードを使用してHTTP全体で提供しています。

    BufferedInputStream input = new BufferedInputStream(p.getInputStream(), (int)FileUtils.BYTES_PER_MEGABYTE * 16);
    OutputStream output = resp.getOutputStream();
    byte[] buffer = new byte[(int) (FileUtils.BYTES_PER_KILOBYTE * 8)];
    do
    {
        int read = input.read(buffer);
        if (read <= 0) break;
        output.write(buffer);           
    } while (true);
    input.close();
    output.close();

次に、クライアント側にHTTP応答を消費するTSVパーサーがありますが、非常に大きな入力では、パーサーが行に間違った数のアイテムがあると報告し、エラーメッセージが解析する行を出力するという奇妙なアーティファクトが見られ始めます。その行はデータのランダムなチャンクになります。つまり、データの行全体ではありません。

私の最初の考えは、生成されているTSVの形式が正しくないことでしたが、ファイルをバックエンドシステムから直接コピーし、3つの独立して記述されたオープンソースTSVパーサー(クライアントコードが使用しているものを含む)で実行することで、これをほぼ排除しました。 )およびそれらはすべて、ローカルファイルで実行するときにファイルを正常に解析できます。

参考までに、使用しているTSVパーサーのコードはこちらです

これは私に2つの可能性をもたらします:

  1. HTTPを介してファイルをコピーするために示したコードには、何らかの欠陥があります。その場合、私が犯したばかげているが自明ではない間違いを誰かに指摘してもらいたいと思います。
  2. BufferedReader.readLine()消費パーサーによって使用されているものは、行全体を読み取ることが保証されていませんか?.Netの低速ネットワークストリームでの奇妙な読み取り動作に噛まれたので、これが当てはまる場合はまったく驚かないでしょう。同様の問題がJavaにも当てはまるのではないかと思います。

それとも私が見落としている他の説明がありますか?

4

1 に答える 1

1

この質問を投稿する際に、私は突然エラーが何であるかを見つけました(通常は!)

ファイルをコピーするために投稿したコードの次の部分が正しくありません。

int read = input.read(buffer);
if (read <= 0) break;
output.write(buffer);

代わりに、次のようにする必要があります。

int read = input.read(buffer);
if (read <= 0) break;
output.write(buffer, 0, read);

問題は、入力からの読み取りがバッファーのサイズよりも少ない場合でも、常にバッファー全体を出力ストリームに書き込んでいたことです。これは、ファイルの最後に、データの最後のチャンクと残りのバッファーに残っているものをすべて出力することを意味します。したがって、データのランダムなチャンクが残ります。

于 2012-07-03T20:56:36.540 に答える