web-dev-qa-db-ja.com

Java

私のJavaプログラムは、他のプログラムによってロックされている可能性のあるファイルを読み込もうとしています。ファイルがロックされているかどうかを確認し、ロックされている場合は解放されるまで待機します。この?

JavaプログラムはWindows 2000サーバーで実行されています。

23
Hellnar

SunのJVMを備えたWindowsでは、FileLocksは適切に機能するはずですが、JavaDocsは信頼性を曖昧にしています(システム依存)。

それでも、Javaプログラムで、いくつかのotherプログラムがファイルをロックしていることを認識するだけでよい場合は、FileLocksと格闘する必要はありませんが、それがロックされている場合は失敗するファイルへの書き込みを試行するだけです。実際のシステムでこれを試行することをお勧めしますが、以下の動作が見られます。

File f = new File("some-locked-file.txt");
System.out.println(f.canWrite()); // -> true
new FileOutputStream(f); // -> throws a FileNotFoundException

これは奇妙なことですが、プラットフォームの独立性を高く数えずに、システムが同じ動作を示す場合は、これをユーティリティ関数にまとめることができます。

現在のJavaバージョンでは、残念ながらファイルの状態の変化について通知する方法はありません。そのため、ファイルが書き込まれるまで待つ必要がある場合は、今すぐすべてを試してから確認する必要があります他のプロセスがロックを解除した場合はわかりませんが、Java 7の場合、新しいWatchServiceを使用してそのような変更について通知される可能性があります。

13
jarnbjo

Windowsで動作するはずです。

File file = new File("file.txt");
boolean fileIsNotLocked = file.renameTo(file);
33
Vlad

そのファイルを使用するすべてのJavaアプリケーションで FileLock を使用し、それらを同じJVM内で実行させます。それ以外の場合、これは確実に実行できません。

5
Ben S

ファイルに排他ロックをかけることができます。排他ロックを取得できない限り、別のプログラムがファイルをロック(排他または共有)します。

2
Ruben Faelens

複数のプロセス(JavaとJava以外)が混在している可能性がある)がファイルを使用している可能性がある場合は、 FileLock を使用します。ファイルロックを正常に使用することは、それらが「アドバイザリ」であることを思い出すことです。ロックは、チェックした場合に表示されることが保証されますが、忘れた場合でもファイルへの操作を停止することはありません。アクセスするすべてのプロセスファイルは、ロックプロトコルを使用するように設計する必要があります。

2
erickson

最善の方法はFileLockを使用することですが、私の場合(jdk 1.6)私は成功して試しました:

public static boolean isFileUnlocked(File file) {
        try {
            FileInputStream in = new FileInputStream(file);
            if (in!=null) in.close();
            return true;
        } catch (FileNotFoundException e) {
            return false;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return true;
    }
2
venergiac

Windowsでのみテスト:次のようにファイルがロックされているかどうかを確認できますvenergiac回答:(file.exist())ファイルが存在するかどうかを確認しますが、FileNotFoundExceptionを使用するとロックされます!このメッセージが表示されます(別のプロセスで使用されているため、プロセスはファイルにアクセスできません)

        public static boolean isFilelocked(File file) {
                try {

                    FileInputStream in = new FileInputStream(file);
                    in.close();
                    return false;
                } catch (FileNotFoundException e) {
                    if(file.exist()){ 
                       return true;
                     }
                     return false;
                } catch (Exception e) {
                    e.printStackTrace();
                }

                return false;
            }
0

Amjad Abdul-Ghaniの回答を改善しました。ファイルから読み取ろうとするまで、エラーは発生しませんでした。

public static boolean isFilelocked(File file) {
     try {
         try (FileInputStream in = new FileInputStream(file)) {
             in.read();
             return false;
         }
     } catch (FileNotFoundException e) {
         return file.exists();
     } catch (IOException ioe) {
         return true;
     }
 }
0
Brook

Windowsの場合、次のものも使用できます。

_new RandomAccessFile(file, "rw")
_

ファイルが排他的にロックされている場合(MS Wordなどによって)、例外があります:Java.io.FileNotFoundException: <fileName> (The process cannot access the file because it is being used by another process)。この方法では、チェックのためだけにストリームを開いたり閉じたりする必要はありません。

注-ファイルが排他的にロックされていない場合(たとえばNotepad ++で開かれている場合)も例外はありません。

0
Dimitar II

LinuxのSmb共有にアクセスできるWindowsで回答の組み合わせ(@vlad)を試しましたが、うまくいきました。最初の部分は、Excelのようなロックには十分でしたが、一部のエディターには不十分でした。両方の状況をテストするために、2番目の部分(名前の変更)を追加しました。

public static boolean testLockFile(File p_fi) {
    boolean bLocked = false;
    try (RandomAccessFile fis = new RandomAccessFile(p_fi, "rw")) {
      FileLock lck = fis.getChannel().lock();
      lck.release();
    } catch (Exception ex) {
      bLocked = true;
    }
    if (bLocked)
      return bLocked;
    // try further with rename
    String parent = p_fi.getParent();
    String rnd = UUID.randomUUID().toString();
    File newName = new File(parent + "/" + rnd);
    if (p_fi.renameTo(newName)) {
      newName.renameTo(p_fi);
    } else
      bLocked = true;
    return bLocked;
  }
0
Claudio