0

それで、ファイルをロックして読み取ろうとしましたが、IOExceptionが発生しました。理由は何ですか?

public static void main(String[] args){
    File file = new File("C:\\dev\\harry\\data.txt");

    FileReader fileReader = null;
    BufferedReader bufferedReader = null;
    FileChannel channel = null;
    FileLock lock = null;
    try{
        channel  = new RandomAccessFile(file, "rw").getChannel();
        lock = channel.lock();
        fileReader = new FileReader(file);
        bufferedReader = new BufferedReader(fileReader);
        String data;
        while((data = bufferedReader.readLine()) != null){
            System.out.println(data);
        }
    }catch(IOException e){
        e.printStackTrace();
    }finally{
        try {
            lock.release();
            channel.close();
            if(bufferedReader != null) bufferedReader.close();
            if(fileReader != null) fileReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

そして私はこのエラーを受け取りましたIOException: The process cannot access the file because another process has locked a portion of the file

4

3 に答える 3

3

コメントの代わりに回答としてこれを追加することもできます。

APIを使用する場合FileLockは、対応するNIOファイルAPIを使用する必要があります。

于 2011-06-14T14:35:12.383 に答える
1

ここから私の答えを再現し(削除された場合)、Jeff Fosterのフィードバックを追加します:

例外のインスタンスがスローされたことを考慮するとOverlappingFileLockException、同じプロセス内の別のスレッドが同じファイルをロックしようとしているように見えます。これはAとBの間の競合ではなく、lock()メソッドに関するAPIドキュメントを参照し、それがOverlappingFileLockExceptionをスローする条件の場合、B内の競合です。

要求された領域と重複するロックがこのJava仮想マシンによってすでに保持されている場合、または別のスレッドがこのメソッドですでにブロックされており、同じファイルの重複領域をロックしようとしている場合

これを防ぐ唯一の解決策は、B内の他のスレッドが、同じファイルまたはファイル内の同じ重複領域でロックを取得できないようにすることです。

スローされるIOExceptionことには、もう少し興味深いメッセージがあります。おそらく上記の理論を裏付けるものですが、ソースコード全体を見ないと何も確認できません。このlockメソッドは、排他ロックが取得されるまでブロックされると予想されます。取得した場合は、ファイルからの読み取りに問題はないはずです。1つの条件を除いて。Fileオブジェクト(つまり、2番目/別のファイル記述子)を使用して、ファイルが別のスレッドの同じJVMによってすでに開かれている(およびロックされている)場合、最初のファイル記述子での読み取りの試行は失敗します。ロックが取得された場合(結局のところ、ロックは他のスレッドをロックアウトしません)。

改善された設計は、各プロセスに単一のスレッドを持ち、ファイルの排他的ロックを(単一のFileオブジェクトまたは単一のファイル記述子を使用しながら)特定の時間だけ取得し、で必要なアクティビティを実行することです。ファイルを作成し、ロックを解除します。

Jeffが指摘したように、NIO APIを使用すると、おそらく問題が解決するでしょう。これは完全に、FileReader APIが新しいファイル記述子を開く可能性があるためです。これは、ロックが取得されたものとは異なります。

于 2011-06-14T14:39:33.413 に答える
0

たぶんあなたが欲しいものはもっと似たようなものです:

FileInputStream fis = new FileInputStream(file);
channel = fis.getChannel();
channel.lock();
bufferedReader = new BufferedReader(new InputStreamReader(fis));
于 2011-06-14T14:35:15.567 に答える