タイムスタンプが変わらないファイルを読み込むときの注意

レアケースですが、知り合いから相談を受けて調べた結果のメモ。
InputStreamはどうやらファイルをキャッシュするらしく、タイムスタンプが変わらず内容だけ変わる場合だと、変更前のファイルの内容を返してくれます。
以下のソースを実行してみると、それがわかります。

#codeprettify{{ package test.io;

import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException;

public class FileCopyTest {

	public static void main(String[] args){
		File f = null;
		f = new File("./test.txt");
		fileOut(f, "ABC");
		fileRead(f);
		f = new File("./test.txt");
		fileOut(f, "EFG");
		fileRead(f);
	}
	private static void fileRead(File f){
		FileInputStream fis = null;
		byte[] buff = new byte[(int)f.length()]; 
		try {
			fis = new FileInputStream(f);
			fis.read(buff);
			System.out.println(new String(buff));
		} catch (FileNotFoundException e) {
		} catch (IOException e) {
		}
	}
	private static void fileOut(File f, String data){
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(f);
			fos.write(data.getBytes());
			fos.close();
		} catch (FileNotFoundException e) {
		} catch (IOException e) {
		}
		f.setLastModified(0);
	}

} }}

このソースの実行結果は

ABC
ABC

と出てきます。

じゃぁ、どうしようかという話になりますが、最終更新日を操作することで、読み込みが可能となります。

#codeprettify{{ package test.io;

import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException;

public class FileCopyTest {

   public static void main(String[] args){
       File f = null;
       f = new File("./test.txt");
       fileOut(f, "ABC");
       fileRead(f);
       f = new File("./test.txt");
       fileOut(f, "EFG");
       fileRead(f);
   }
   private static void fileRead(File f){
       FileInputStream fis = null;
       byte[] buff = new byte[(int)f.length()]; 
       long l = f.lastModified();
       f.setLastModified(l + 1);
       try {
           fis = new FileInputStream(f);
           fis.read(buff);
           System.out.println(new String(buff));
       } catch (FileNotFoundException e) {
       } catch (IOException e) {
       }
       f.setLastModified(l);
   }
   private static void fileOut(File f, String data){
       FileOutputStream fos = null;
       try {
           fos = new FileOutputStream(f);
           fos.write(data.getBytes());
           fos.close();
       } catch (FileNotFoundException e) {
       } catch (IOException e) {
       }
       f.setLastModified(0);
   }

} }} 何やってるかというと、

  1. ファイルを読み込む前に、ファイルの最終更新日をlastModified()メソッドで取得
  2. 取得した最終更新日に1を加算
  3. ファイルを読み込む
  4. 最終更新日を元に戻す

実行結果は

ABC
EFG

となります。
この方法がいいか悪いかわかりませんが、このようなケースに遭遇した場合にはいいかもしれません。


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2011-12-05 (月) 11:15:19