3

XML ファイルを検証しており、検証の結果に応じて、ファイルを別のフォルダーに移動する必要があります。

XML が有効な場合、バリデーターは値を返し、問題なくファイルを移動できます。スキーマに従って XML が有効でない場合にも、同じことが起こります。

ただし、XML の形式が適切でない場合、バリデーターは例外をスローし、ファイルを移動しようとすると失敗します。ファイルを保持しているメモリのどこかにまだハンドルがあると考えています。ファイルを移動する前に System.gc() を配置しようとしましたが、問題はSystem.gc()解決しましたが、解決策としてはありません。

コードは次のようになります。StreamSource を作成する File オブジェクトがあります。その後、StreamSource がバリデーターに渡されます。XML が整形式でない場合、SAXException がスローされます。例外処理では、.renameTo() メソッドを使用してファイルを移動します。

sc = new StreamSource(xmlFile);
validator.validate(sc);

私たちが試したキャッチでは

validator.reset();
validator=null;
sc=null;

しかし、まだ.renameTo()ファイルを移動できません。キャッチを入れればSystem.gc()、動きは成功します。

誰かがこれなしでこれをソートする方法を教えてもらえますかSystem.gc()?

JAXP と saxon-9.1.0.8 をパーサーとして使用します。

どうもありがとう

4

5 に答える 5

5

を作成してFileInputStreamに渡し、完了したら をStreamSource閉じてみてくださいFileInputStream。を渡すことでFile、ファイル ハンドルをいつ、どのように閉じるかを制御できなくなります。

于 2011-08-01T15:49:58.667 に答える
3

を設定sc = nullすると、ガベージ コレクターに対して、StreamSource ファイルが使用されなくなり、収集できることが示されます。ストリームはdestroy()メソッド内で閉じられるため、ガベージ コレクションが行われると閉じられるため、Windows システムで移動できます (Unix システムではこの問題は発生しません)。

GC を手動で呼び出さずに問題を解決するには、単にsc.getInputStream().close()beforeを呼び出しますsc = null。とにかくこれは良い習慣です。

一般的なパターンは、try .. finallyファイルハンドルの使用法をブロックすることです。

try {
    sc = new StreamSource(xmlFile);
    // check stuff
} finally {
    sc.getInputStream().close();
}
// move to the appropriate place

Java 7 では、代わりに新しいtry with resourcesブロックを使用できます。

于 2011-08-01T15:48:56.270 に答える
1

キャッチで sc.getInputStream().close() を試してください

于 2011-08-01T15:49:44.737 に答える
1

既に与えられた 3 つの答えはすべて正しいです。StramSource を直接呼び出すか、ストリームを取得して閉じるか、自分でストリームを作成して閉じるかのいずれかで、基になるストリームを閉じる必要があります。

ただし、少なくとも3年間、Windowsでこれが発生しているのをすでに見てきました。ストリームを閉じても、実際にはすべてのストリームで、ファイルを移動または削除しようとすると、例外がスローされます..でなければ... System.gc() を明示的に呼び出します。

ただし、System.gc() は、JVM がガベージ コレクションのラウンドを実際に実行するために必須ではないため、JVM が可能性のあるすべてのガベージ オブジェクトを削除することを義務付けられていない場合でも、それを確認する実際の方法はありません。ファイルは「今すぐ」削除できます。

明確な説明はありません。おそらく、java.io の Windows 実装がファイル ハンドルを何らかの形でキャッシュし、ハンドルがガベージ コレクションされるまでファイル ハンドルを閉じないことしか想像できません。

報告されていますが、私は確認していませんが、java.nio はファイル記述子に対してより低レベルの制御を行っているため、この動作の影響を受けません。

私が過去に使用した解決策ですが、これは非常にハックであり、次のことでした。

  1. 削除するファイルを「リスト」に入れる
  2. バックグラウンド スレッドでリストを定期的にチェックし、System.gc を呼び出して、それらのファイルの削除を試みます。
  3. 削除できたファイルをリストから削除し、まだ準備ができていないファイルをそのままにしておきます。

通常、「ラグ」は数ミリ秒程度ですが、ファイルがもう少し長く存続するという例外もあります。

これらのファイルに対しても deleteOnExit を呼び出すことをお勧めします。これにより、スレッドがいくつかのファイルのクリーニングを完了する前に JVM が終了した場合、JVM はそれらのファイルを削除しようとします。ただし、当時の deleteOnExit には独自のバグがあり、ファイルを正確に削除できなかったので、削除しませんでした。多分今日それは解決され、deleteOnExit を信頼することができます。

これは私が最も厄介でばかげている JRE バグであり、まだ存在しているとは信じられませんが、残念ながら、最新の JRE がインストールされた Windows Vista でちょうど 1 か月前に発生しました。

于 2011-08-01T16:02:26.663 に答える