3

ソフトウェアの奇妙なバグを解決することに気付きました。問題は、アプリケーションを実行可能な JAR にパッケージ化した場合にのみ発生することです。

問題はこの単純なコードにありました:ループカウンターを追加して、サイクルが何回行われたかをカウントします

private static byte[] read(InputStream source) {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    int loopCounter = 0;
    int bytesRead;

    try {
        byte[] buffer = new byte[4096]; 

        while ((bytesRead = source.read(buffer)) != -1) {
            out.write(buffer, 0, bytesRead);
            loopCounter++;
        }

    } catch (IOException e) {
        e.printStackTrace();
    }

    return out.toByteArray();
}

例:

source = ClassLoader.class.getResourceAsStream("file.lol");

loopCounter in Eclipse = 1366
loopCounter in JAR     = 1405

私の質問は、同じ InputStream でこの大きな違いがあるのはなぜですか?

編集:コードを正しいものに変更しますが、loopCounters はまだ異なります。

4

1 に答える 1

7

InputStream.read()一度にバッファ全体を埋めることを保証するものではないため、実際に読み取ったバイト数を追跡​​する必要があります。

byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = source.read(buffer)) != -1) {
    out.write(buffer, 0, bytesRead);
    loopCounter++;
} 

そのため、反復ごとに読み取られるバイト数が の実装によって異なることは驚くに値しませInputStreamん。したがって、反復回数も異なる可能性があります。

実際には、 の特定の呼び出しによって読み取られるバイト数はInputStream.read()、多くの要因に依存します。

最初の要因は の実装ですInputStream。アプリケーションを Eclipse から実行する場合InputStreamは、ファイル システムから直接リソースを読み取る を使用しますが、jar ファイルから実行する場合は、jar ファイルからInputStreamリソースを抽出する を使用します。明らかに、jar ファイルの解凍アルゴリズムの内部構造が、取得するチャンクのサイズに影響を与える可能性があります。

もう 1 つの要因は、基盤となる環境の動作です。たとえば、ファイル システムからファイルを読み取るシステム コールは、オペレーティング システムの内部動作などに応じて、さまざまなサイズのチャンクを返す場合もあります。

于 2012-06-06T13:02:35.000 に答える