今作成しているjavaのアプリケーションがあるのですが、
うまく動きません。
ファイルサーバにアップロードされるファイルを数秒間ごとに
監視し、アップロードされれば自動で別のディレクトリにコピ
ーするというアプリケーションを作成しております。
で、MAC osX server上で動かすと正常に動くのですが、
Windows 2000 server上だと正常に動きません。
プログラムの流れとしてはFile型のorigオブジェクト(元ファイル)
と、File型のcopyオブジェクト(移動先のファイル)を用意し、
BufferedInputSteramで読み取って、BufferedOutputStreamで
書き出す、というものです。
うまく動かない箇所は、origファイルがまだアップロード中で
ある場合そのファイルに対してFileInputStreamを用意しようと
すると、FileNotFoundExceptionが発生するだけでなく、その
ファイルが消去されてしまうのです。恐らくはJavaではなく、
OSがコピーエラーが発生したかのように扱ってしまい、ファイル
を消去してしまうのではないかと思っているのですが。(osXでは
動くので)
FileInputStream fis = new FileInputStream(orig);
この行で例外発生!ファイルが消える。
そこでFileInputStreamを用意する前に、そのファイルがコピー中
であるのか、コピーが終わっているのかを調べることができるの
でしょうか、というのが私の質問です。あるいは、全く違った側面
からの回避策でも結構です。
ちなみにorig.exists()はアップロード中であってもtrueが返され
ます。
javaはプラットホームに依存しないと信じてたのに大きな落とし穴
でした。以下にソースの一部を記述しておきますので、よろしく
おねがいします。
No.5ベストアンサー
- 回答日時:
気になったんでちょっと試してみました。
環境は違うんですが、おそらく同じような結果が得られました。
環境:WindowsXP
JVM:JDK1.3.1_02
コピー中のファイルに対しては確かにexistsがtrueになりました。
InputStreamを取得すると、
java.io.FileNotFoundException: test.txt (プロセスはファイルにアクセスできません。別のプロセスが使用中です。)
という例外がthrowされました。
ここまで同じような結果が得られるのですが、
私が試した結果ではファイルは消えません。そのままコピーが継続されました。
例外が発生したときに何かしていますか?
ファイルが消えてしまうのは何か別の原因ではないでしょうか?
この回答への補足
貴重な情報ありがとうございます。すぐにXPを用意できないので試してないのですが、他を色々試すうちに新しいことがわかりました。それはファイルをコピーしているクライアントのOSがmacOSだとファイルが消去され、クライアントがwindowsだとおっしゃる通り、FileNotFoundExceptionの後、正常にコピーされるということです。つまりなんらかの形でOS間の互換性の問題があるということでしょうか。
原因がjavaとは関係の無いところにあるのでしょうけど、クライアントをwin系のOSに限定することは出来ないのです。なんとかjava側で回避策が作れないものでしょうか?
ちなみに、例外をcatchするブロックではデバグの為にprintStackTrace()を行っている以外何もやっておりません。さらにプログラムのその後の処理を削除しても結果は同じなので他にjavaのプログラムがファイルを消去するようなことは考えられません。
お騒がせいたしました。結局XPでは試せなかったのですが、FileInputStreamを取得せずとも、FileクラスのrenameTo()メソドでファイルパスを変えてやることにより、ファイルの移動が可能なことが解りました。(これって常識?)
このメソドでは、色々な状況でテストしてみましたが、コピー中のファイルに対して行っても、ファイルが消える、壊れる、といった現象は起きません。
もっともこの場合ファイルのコピーではなく移動なのですが、今回やりたかったことはとりあえずこれで実現できました。
いろいろ試していただいたようなので、報告を兼ねてお礼いたします。では。
No.4
- 回答日時:
実は JVM の障害で、バージョンを上げたり/下げたりすると動く、ってことは…
後は、ファイルの時刻をコピー開始の時刻とみなして、適当な時間が経ってからコピーかなあ。
この回答への補足
そうですね。原因がJVMの方にあるということも考えられなくはないです。
ですが、osXでもwin2000でも同じsdk1.4.1で試して、動きが異なったことからも、原因はos環境ではないかとまず疑ったのです。さらに新しくわかったのですが、win2000環境でもファイルをアップロードするクライアントが同じwin2000の端末からだと、ファイルが消える現象は起きません。やはり問題はos環境と考えて良いのではと思っています。
また、ファイルの更新時刻で判断する方法ですが、クライアント数が多く頻繁に使われるサーバー上でのプログラムなので、厳密で無い処理は避けたいと思っています。
ともかく、意見交換ができて非常にためになります。ありがとうございます。
いろいろお騒がせいたしましたが、結局FileInputStreamを使わず、renameTo()メソドを試してみたらファイルの移動が問題なく実現いたしました。
問題が全て解決したわけではありませんが、一応自分のやりたかったことは実現できました。ありがとうございました。
No.3
- 回答日時:
exists()がtrueを返すのに、InputStreamを作ろうとすると、
FileNotFoundExceptionを返すんですか。
それは難しいですね。
試していないんで分からないんですが、
アップロード中のファイルに対して、
isFile()とか、canRead()とか、length()とかを
チェックしてみて、アップロードが完了したファイルと、
相違点があれば、それを基準にできるかも。
あとは、一定時間サイズが増加しなかったら、
アップロードしたとみなすとか。でも、これだと完全じゃないかも
知れませんね。
この回答への補足
ヤケになっていろいろ試しましたが、
コピー中のオブジェクトに対して
canRead() : true
canWrite() : true
delete() : true
isFile() : true
length() : 完全なファイルサイズ(コピー後と同じ)
となります。無理っぽいですね。
No.2
- 回答日時:
確実に問題を回避できる保証はありませんが、サイズのチェックをしたらどうでしょう。
まず、ファイルを見つけたら、ファイルパスとサイズを保持しておいて、次の監視タイミングで
前回(*)のサイズと同じであれば、コピーが完了しているものとして、処理を行う。
(*) 回線の重さ次第では、監視間隔以内にコピーがされていない可能性もあるので、
二回後、とか、三回後とか調整してみる
# ま、こういった処理は General には書けない、ってことでしょうね
この回答への補足
回答ありがとうございます。
実はサイズのチェックも試してみたんですが、コピーが始まった時点で完全なファイルとしてのサイズが記録されるようで、コピーしながらファイルサイズが大きくなるというものでは無いようです。(これもOS依存かもしれませんが)
結局ファイルのコピーという部分をOS任せにしている以上、難しいのですね。
それにしても「javaでの例外の発生」-->「os側でのファイルの消去」というwindowsのふるまいは納得いきません。
裏技のようなテクニックでもないものかと。。。
No.1
- 回答日時:
いろんな方法があると思いますが、
監視プログラムの方の修正ではなく、
アップロードプログラム(Servlet?)の方の修正になってしまいますが、
アップロードするファイルが作成中の間は、テンポラリなファイルに
書き込んで、アップロード完了後はリネームするような動作にしたら
どうでしょうか?
例
アップロード中:file_123456.tmpに書き込み
↓
アップロード完:file_123456.txtにリネーム
監視プログラムは、*.tmpファイルは対象外にして、
アップロードが完了したファイル(*.txt)だけを監視する。
この回答への補足
早速の回答ありがとうございます。
アップロードと書きましたが、それは単なるイントラ内でのファイルのコピーです。従ってそこにはアプリケーションは存在しません。つまりどうしても監視側でコピー完了を確認しなければならないんです。
いかがでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Windows 10 USBにwindows10をいれて起動する方法 5 2022/04/14 14:29
- Visual Basic(VBA) 動かなくなってしまった古いVBAを動くようにしたい 8 2022/09/20 13:57
- その他(コンピューター・テクノロジー) <a href="file:///フォルダ名/ファイル名">リンクテキスト</a>について 1 2023/04/06 22:40
- その他(プログラミング・Web制作) セレクトボックスで選択された値をコントローラーで使用したい 2 2022/07/26 16:41
- Windows 10 explorerをedgeで開く方法 2 2022/06/05 14:59
- Excel(エクセル) 【マクロ】エラーが発生⇒実行時エラー58既に同名のファイルが存在 5 2022/08/31 10:03
- Visual Basic(VBA) vba メモリ節約 3 2022/09/16 21:45
- UNIX・Linux JSLinuxについて。 Linuxのこの手順のプログラミングは合っているでしょうか。 ①ホームディ 2 2022/06/20 15:33
- Windows 10 Windows10の回復環境 2 2023/02/03 19:13
- Excel(エクセル) エクセルでシートを別のブックにコピーや移動する際に出るエラーのような窓を回避するには? 1 2023/06/05 21:51
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
0バイトのテキストファイル
-
VBAで、JPG写真の撮影日時を読...
-
RPGでメッセージファイル利用
-
VB6.0のメモリリークについて
-
vbaの構文の修正相談(xmlファ...
-
【VBA】印刷マクロのループ処理...
-
Eclipseで検索ができなくなった
-
タスクバーのアイコンについて
-
2GB以上のファイルを扱う方法
-
サイトマップにサブドメインを...
-
ファイル内容を比較する方法
-
PHPからベーシック認証のかかっ...
-
VB2008 iniファイルの全セクシ...
-
【Excel VBA】取り込んだファイ...
-
Javaのファイルダウンロードに...
-
HTMLテキストリンクでExcelファ...
-
VB6 実行ファイルにデータの保存
-
Perlで2GBを超える大きいファイ...
-
BASP21のファイルアップロード...
-
msgget()で指定するkey値について
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
0バイトのテキストファイル
-
【Excel VBA】取り込んだファイ...
-
HTMLテキストリンクでExcelファ...
-
VBAで、JPG写真の撮影日時を読...
-
Eclipseで検索ができなくなった
-
vbaの構文の修正相談(xmlファ...
-
2GB以上のファイルを扱う方法
-
サイトマップにサブドメインを...
-
main関数のコマンドライン引数...
-
ファイル更新日取得
-
ファイル作成日時と更新日時を...
-
VB6.0のメモリリークについて
-
C++によるファイル送受信プログ...
-
リソースファイルを認識してく...
-
ファイルのダウンロードが遅い
-
C++.NET 2003 「空のドキュメ...
-
Javaのファイルダウンロードに...
-
HTMLまたはJavaScriptでフ...
-
【VBA】複数CSVの特定範囲を1つ...
-
C#について質問【複数の.datフ...
おすすめ情報