QA@IT

ファイルの読み込み時に排他ロックをかけたい

4631 PV

ファイルの読み込み時に排他ロックをかけたいと思っています。

環境はjava7,windows7です。
フォルダにコピーされたビットマップファイルを読み込む際に、コピーが終わってから読
み込みたいので、ファイルに排他コピーをかけて、その後読み込もうと思っています。
現在試しているコードは以下になります。

package test;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;

public class FileLockMove {

    public static void main(String[] args) {
        FileSystem fs = FileSystems.getDefault();
        File dir = new File("c:/test_source/");
        while(true){
            for (File file : dir.listFiles()) {
                try (FileChannel fc = (new RandomAccessFile(file, "rw")).getChannel()){
                    FileLock lock = fc.tryLock();
                    if(lock != null){
                        System.out.println("lock is not null\t" + file.getName());
                        System.out.println("addBody: " + file.getAbsolutePath() + "\t" + file.length());
                    }else{
                        System.out.println("lock is null\t" + file.getName());
                        continue;
                    }
                } catch (Exception e) {
                    System.out.println("ファイル処理失敗:" + file.getName()+"\t" + e.getMessage());
                }
                try {
                    Files.move(file.toPath(), fs.getPath("c:/test_dest/",file.getName()));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

本来フォルダにファイルをコピーするプログラムはjavaではないのですが、
ロックがかけられているか確認するために、わざとゆっくりコピーするプログラムを
作成しました。

package test;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;

public class YukkuriFileCopy{
    public static void main(String[] args) {
        String source = "どこかファイルがある場所";
        String dst ="C:/test_source/";
        File file = new File(source);
        File[] files = file.listFiles(new FilenameFilter() {

            @Override
            public boolean accept(File dir, String name) {
                if(name.matches(".*\\.bmp")){
                    return true;
                }
                return false;
            }
        });
        for(File f: files){
            copyStream(f, dst);
        }

    }

    static void copyStream(File source,String dst){
        try(BufferedInputStream br = new BufferedInputStream(new FileInputStream(source))){
            BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dst+source.getName()));
            byte[] buff = new byte[100];
            int len = -1;
            while((len = br.read(buff)) >-1){
                out.write(buff,0,len);
                out.flush();
                Thread.sleep(100);
            }
            out.close();
            System.out.println(source.getName() + "\tコピー完了");
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}


このときにファイルのコピーが終わってない状態(中途半端なサイズ)でlockが取得できてしまいます。
その後のmoveの処理では
java.nio.file.FileSystemException: プロセスはファイルにアクセスできません。別のプロセスが使用中です。
とでるので、ロックが取得できないと思っていたのですが、ロックは取得できているようです。。
なにかロックの理解が間違っているのでしょうが、原因がわからず困っています。
皆さまのお知恵をお貸しください。
また同様のシチュエーションで別の解決方法で乗り切った方がいたら教えてくださいますか。
よろしくお願い致します。

ウォッチ

この質問への回答やコメントをメールでお知らせします。