4

タイルが言ったように、私の Java アプリケーションは、Eclipse での開発中に正常に動作するため、動作しません。

Eclipse でアプリケーションのビルドとテストを完了しました。私が期待したようにうまく動作します。クライアントがシステムで使用できないように、実行可能なjarとして展開する必要がありました。Eclipseにエクスポートして、実行可能なjarにしました。実行可能な jar を実行すると、アプリケーションはしばらく正常に動作し始め、ファイルの読み取りで停止します。Eclipseの同じコードで問題はありませんでした。

動作しないと思われるソース スニペットは次のとおりです。

            sfis = new SmbFileInputStream(sFile);
            in = new BufferedInputStream(sfis);

            byte buf[] = new byte[(int)sFile.length()];
            int pos = 0;
            int size = 10;
            int temp;

            while((size=in.read(buf, pos, size)) > 0){
                pos += size; 
                temp = buf.length - pos;
                if(temp < 10){
                    size = temp;
                }
            }

Eclipse では問題ありません。SMB 接続からデータを完全に読み取り、ジョブを完了します。しかし、jar アプリケーションからは、ある時点で while ループ内の入力ストリームからの読み取りを停止するようです。これは私が今まで経験したことのない非常に奇妙なケースです。そして、私はこれに対する解決策を見つけることができません。

これは、私のコードまたは Eclipse によって誤って作成された可能性のある jar ファイルが原因ですか?

- - - - - 追加情報 - - - - - - - - - -

Edmondo1984 の大きな助けを借りて、jar プログラムが停止する場所を見つけました。SmbFile から入力ストリームに移動すると、新しいスレッド jcifs.util.transport.Transport が作成され、スレッドは単純にブロックされ、アプリケーションは別の jcifs.util.transport.Transport を作成します。8 つまたは 9 つの jcifs.util.transport.Transport スレッドを作成した後、スタックして何もしません。

同じコード、同じ jcifs ライブラリ。ただし、Eclipse 上で実行する場合と、実行可能な jar としてローカル マシン上で実行する場合では、動作が異なります。なぜこれが起こっているのか分かりません。

4

3 に答える 3

2

「ストリームにこれ以上何もない」の戻り値は-1( Javadocを参照) です。

in.read(buf, pos, size)しようとしても、基礎となるものがまだ利用できない場合に何が起こるか想像してみてください。その後、呼び出しはすぐに戻り値0(ゼロ) を返します。このようにして、ループ条件が false と評価され、ループが終了します。だから私はあなたと比較するべきだと思います!= -1

size = 0別の考えられる問題: (上記のシナリオが原因で) の場合に何が起こるかを検討することもできますtemp >= 10。読み取る最大バイト数としてsizetoの値を直接フィードバックするため、 との比較を既に修正していると仮定すると、無限ループに陥る可能性があります。in.read(buf, pos, size)!= -1

于 2012-07-19T09:48:28.860 に答える
1

ストリームをいじるとき、そのような振る舞いは頻繁に起こります。小さなアルゴリズムの誤りは、さまざまな環境でさまざまな症状を引き起こす可能性があります。

「デバッグ」情報をコンソールに出力して、コードが停止している場所と理由をよりよく理解できます。私はそれがreadメソッドにあるとかなり確信しています。

コードにはいくつか問題がありますが、最も悪名高いのはブロックです。

temp = buf.length - pos;
if(temp < 10){
  size = temp;
}

なんで?残りのバイト数が10以下の場合は、次のread()でそれらを読み取ろうとします。そうしないと、読みすぎになる可能性があります(ファイル全体のサイズを再度)。Eclipseで実行している場合、ファイルはおそらく最初のread()で読み取られていますが、Eclipseからは読み取られていないようです。コードを次のようなものに変更してみてください。

FileInputStream sfis = new FileInputStream(sFile);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte buf[] = new byte[4096];
int read = sfis.read(buf);
while(read>0){
  baos.write(buf, 0, read);
  read = sfis.read(buf);
}
sfis.close();

また、このタイプのコードを常に記述する代わりに、 ApacheのJavaIOユーティリティコードを使用することを検討してください。JavaのIOには多くの定型文が必要であり、優れたプログラマーにはもっと良いことがあります。

補足:ファイルをメモリに読み取ることは、通常は悪い考えです。データ全体を何らかの方法で変換する場合を除いて、ストリーミングの方が常に優れています。あなたのプログラムが何のためにあるのかわかりませんが、これを覚えておいてください:10GBのファイルを読み込もうとするとどうなりますか?またはいくつか?

ハッピーコーディング、

于 2012-07-19T10:37:35.570 に答える