Writing /volume1/Web/Public/dokuwiki/data/log/deprecated/2024-11-14.log failed
Writing /volume1/Web/Public/dokuwiki/data/log/deprecated/2024-11-14.log failed
File.delete() problem in Java
今、取り掛かっているプロジェクトでリソースpropertiesファイルの内容を変更するツールを開発している。
主なロジックの流れは次のとおり。
- xxx.propertiesのコピーxxx.properties_orgを作成する。
- xxx.properties_orgのバックアップfileであるxxx.properties_org_backを作成する。1)
- xxx.properties_orgを読込み、変換したい文字列で変換して、xxx.properties_tempファイルで出力する。2)
- xxx.properties_orgファイルを削除する。
- xxx.properties_tempファイル名をxxx.properties_orgで修正する。(File.renameTo)
- xxx.properties_orgファイルからnative2asciiを用いてxxx.propertiesファイルを出力する。3)
- 正常に処理が終われば、xxx.properties_orgとxxx.properties_org_backを削除する。 エラーが発生する場合、xxx.properties_orgを削除して、xxx.properteis_org_backを元にnative2asciiを利用しxxx.propertiesで変換する。
最後の処理で理解出来ないことが起こった。xxx.properties_org_backファイルは削除出来るけど、xxx.properties_orgを削除しようとした瞬間、xxx.properteisファイルも一緒に消える妙な現象だ。
普通、こんなこと起こるかよ。と思いながら、真相が突き止めたくて一つの実験をすることにした。
実験(1)
実験は削除するにどのくらい掛かるのかを数えてみた。JDK1.5環境で、ログはlog4jを利用した。
String[] orgPropKey = (String[])orgPropList.keySet().toArray(new String[0]); for(int j=0; j<orgPropKey.length; j++){ File orgPropFile = (File)orgPropList.get(orgPropKey[j]); boolean flg = false; int i = 0; do { i++; flg = orgPropFile.delete(); if(flg){ if(logger.isDebugEnabled()){ logger.debug(orgPropFile.getAbsolutePath()+" is deleted!!"); logger.debug("count="+i); } } } while (!flg); }//for
その結果、次のテーブルのようにばらばら~
回数 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
count | 1 | 1* | 4 | 351 | 1* | 198 | 1 | 380 | 270 | 1* |
ここで、asteriskが付いてる時、xxx.proertiesも一緒に削除された。
一緒に削除される原因はまだ定かではないが、いろんな仮説とテストを通じて問題なく、xxx.proerties_orgのみ削除に成功したのが次だ。
解決
先ほどの実験で分かったのがcount=1の場合に問題が起こっていたこと。それで、count=1の場合、削除を禁じる為、xxx.properties_orgファイルを読み取り専用で変更した。
String[] orgPropKey = (String[])orgPropList.keySet().toArray(new String[0]); for(int j=0; j<orgPropKey.length; j++){ File orgPropFile = (File)orgPropList.get(orgPropKey[j]); boolean flg = false; int i = 0; do { i++; if(i==1) { if(orgPropFile.setReadOnly()){ if(logger.isDebugEnabled()) logger.debug("readonly!!"); } } if(logger.isDebugEnabled()) logger.debug("writable :: "+orgPropFile.canWrite()); flg = orgPropFile.delete(); if(flg){ if(logger.isDebugEnabled()){ logger.debug(orgPropFile.getAbsolutePath()+" is deleted!!"); logger.debug("count="+i); } } } while (!flg); }//for
これで実行した結果のログサンプルを紹介する。
[22 5 2008 16:41:17,093] DEBUG (ResourceUpdater.java:87) - D:\workspace\Trans-xxx\WEB-INF\prop\xxx.properties_org_back is deleted!! [22 5 2008 16:41:17,093] DEBUG (ResourceUpdater.java:103) - readonly!! [22 5 2008 16:41:17,093] DEBUG (ResourceUpdater.java:108) - writable :: false [22 5 2008 16:41:17,312] DEBUG (ResourceUpdater.java:108) - writable :: true [22 5 2008 16:41:17,312] DEBUG (ResourceUpdater.java:108) - writable :: true [22 5 2008 16:41:17,328] DEBUG (ResourceUpdater.java:108) - writable :: true [22 5 2008 16:41:17,328] DEBUG (ResourceUpdater.java:108) - writable :: true [22 5 2008 16:41:17,328] DEBUG (ResourceUpdater.java:108) - writable :: true [22 5 2008 16:41:17,328] DEBUG (ResourceUpdater.java:108) - writable :: true [22 5 2008 16:41:17,328] DEBUG (ResourceUpdater.java:108) - writable :: true [22 5 2008 16:41:17,328] DEBUG (ResourceUpdater.java:108) - writable :: true [22 5 2008 16:41:17,328] DEBUG (ResourceUpdater.java:108) - writable :: true [22 5 2008 16:41:17,343] DEBUG (ResourceUpdater.java:108) - writable :: true [22 5 2008 16:41:17,343] DEBUG (ResourceUpdater.java:112) - D:\workspace\Trans-xxx\WEB-INF\prop\xxx.properties_org is deleted!! [22 5 2008 16:41:17,343] DEBUG (ResourceUpdater.java:113) - count=11
ちなみにcountの結果は次のようだった。
回数 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 1 | 1 | 19 | 20 | 7 | 14 | 34 | 8 | 34 | 37 | 38 | 29 | 11 | 11 | 27 | 4 | 28 | 6 | 1 | 1 |
1)
作業中、エラーが発生する場合、元の状態で戻す為に用意する。
2)
読み込む際、charsetは言語に沿って決める(日本語ならShift-JIS)。
3)
Runtime.getRuntime().exec(“native2ascii -encoding ” + charset + “ ” + sourceFilePath + “ ” + makeFilePath);
ここでsourceFilePathはxxx.properties_org, makeFilePathはxxx.propertiesに該当する。
ここでsourceFilePathはxxx.properties_org, makeFilePathはxxx.propertiesに該当する。