アプリ版:「スタンプのみでお礼する」機能のリリースについて

今作成している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はプラットホームに依存しないと信じてたのに大きな落とし穴
でした。以下にソースの一部を記述しておきますので、よろしく
おねがいします。

A 回答 (6件)

気になったんでちょっと試してみました。


環境は違うんですが、おそらく同じような結果が得られました。

環境: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のプログラムがファイルを消去するようなことは考えられません。

補足日時:2002/12/11 20:08
    • good
    • 0
この回答へのお礼

お騒がせいたしました。結局XPでは試せなかったのですが、FileInputStreamを取得せずとも、FileクラスのrenameTo()メソドでファイルパスを変えてやることにより、ファイルの移動が可能なことが解りました。(これって常識?)
このメソドでは、色々な状況でテストしてみましたが、コピー中のファイルに対して行っても、ファイルが消える、壊れる、といった現象は起きません。
もっともこの場合ファイルのコピーではなく移動なのですが、今回やりたかったことはとりあえずこれで実現できました。
いろいろ試していただいたようなので、報告を兼ねてお礼いたします。では。

お礼日時:2002/12/13 16:35

問題のフォルダのオブジェクト.lists()


で、ファイルやサブフォルダがString[]が返りますよね。

これで確認してからでは、いかがでしょうか?

この回答への補足

コピー中のファイルもFile型のオブジェクトとして認識します。

補足日時:2002/12/11 22:12
    • good
    • 0

実は JVM の障害で、バージョンを上げたり/下げたりすると動く、ってことは…



後は、ファイルの時刻をコピー開始の時刻とみなして、適当な時間が経ってからコピーかなあ。

この回答への補足

そうですね。原因がJVMの方にあるということも考えられなくはないです。
ですが、osXでもwin2000でも同じsdk1.4.1で試して、動きが異なったことからも、原因はos環境ではないかとまず疑ったのです。さらに新しくわかったのですが、win2000環境でもファイルをアップロードするクライアントが同じwin2000の端末からだと、ファイルが消える現象は起きません。やはり問題はos環境と考えて良いのではと思っています。
また、ファイルの更新時刻で判断する方法ですが、クライアント数が多く頻繁に使われるサーバー上でのプログラムなので、厳密で無い処理は避けたいと思っています。
ともかく、意見交換ができて非常にためになります。ありがとうございます。

補足日時:2002/12/11 22:20
    • good
    • 0
この回答へのお礼

いろいろお騒がせいたしましたが、結局FileInputStreamを使わず、renameTo()メソドを試してみたらファイルの移動が問題なく実現いたしました。
問題が全て解決したわけではありませんが、一応自分のやりたかったことは実現できました。ありがとうございました。

お礼日時:2002/12/13 16:41

exists()がtrueを返すのに、InputStreamを作ろうとすると、


FileNotFoundExceptionを返すんですか。
それは難しいですね。

試していないんで分からないんですが、
アップロード中のファイルに対して、
isFile()とか、canRead()とか、length()とかを
チェックしてみて、アップロードが完了したファイルと、
相違点があれば、それを基準にできるかも。

あとは、一定時間サイズが増加しなかったら、
アップロードしたとみなすとか。でも、これだと完全じゃないかも
知れませんね。

この回答への補足

ヤケになっていろいろ試しましたが、
コピー中のオブジェクトに対して
canRead() : true
canWrite() : true
delete() : true
isFile() : true
length() : 完全なファイルサイズ(コピー後と同じ)
となります。無理っぽいですね。

補足日時:2002/12/11 15:47
    • good
    • 0

確実に問題を回避できる保証はありませんが、サイズのチェックをしたらどうでしょう。



まず、ファイルを見つけたら、ファイルパスとサイズを保持しておいて、次の監視タイミングで
前回(*)のサイズと同じであれば、コピーが完了しているものとして、処理を行う。

  (*) 回線の重さ次第では、監視間隔以内にコピーがされていない可能性もあるので、
    二回後、とか、三回後とか調整してみる

# ま、こういった処理は General には書けない、ってことでしょうね

この回答への補足

回答ありがとうございます。
実はサイズのチェックも試してみたんですが、コピーが始まった時点で完全なファイルとしてのサイズが記録されるようで、コピーしながらファイルサイズが大きくなるというものでは無いようです。(これもOS依存かもしれませんが)
結局ファイルのコピーという部分をOS任せにしている以上、難しいのですね。
それにしても「javaでの例外の発生」-->「os側でのファイルの消去」というwindowsのふるまいは納得いきません。
裏技のようなテクニックでもないものかと。。。

補足日時:2002/12/11 15:08
    • good
    • 0

いろんな方法があると思いますが、


監視プログラムの方の修正ではなく、
アップロードプログラム(Servlet?)の方の修正になってしまいますが、
アップロードするファイルが作成中の間は、テンポラリなファイルに
書き込んで、アップロード完了後はリネームするような動作にしたら
どうでしょうか?



アップロード中:file_123456.tmpに書き込み
 ↓
アップロード完:file_123456.txtにリネーム

監視プログラムは、*.tmpファイルは対象外にして、
アップロードが完了したファイル(*.txt)だけを監視する。

この回答への補足

早速の回答ありがとうございます。
アップロードと書きましたが、それは単なるイントラ内でのファイルのコピーです。従ってそこにはアプリケーションは存在しません。つまりどうしても監視側でコピー完了を確認しなければならないんです。
いかがでしょうか?

補足日時:2002/12/11 14:43
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!