代码之家  ›  专栏  ›  技术社区  ›  Paralife

如何使用java锁定文件(如果可能)

  •  102
  • Paralife  · 技术社区  · 17 年前

    我有一个Java进程,它使用FileReader打开一个文件。如何防止另一个(Java)进程打开此文件,或者至少通知第二个进程该文件已打开?如果文件已打开(这解决了我的问题),这会自动使第二个进程出现异常吗?还是必须在第一个进程中使用某种标志或参数显式打开它?

    澄清:

    我有一个Java应用程序,它列出一个文件夹,并打开列表中的每个文件进行处理。它一个接一个地处理每个文件。每个文件的处理包括读取文件和根据内容进行计算,大约需要2分钟。我还有另一个Java应用程序,它也做同样的事情,但却在文件上写。我想要的是能够同时运行这些应用程序,所以场景是这样的。ReadApp列出文件夹并查找文件A、B、C。它打开文件A并开始读取。WriteApp列出文件夹并查找文件A、B、C。它打开文件A,看到文件A处于打开状态(通过异常或其他方式),然后转到文件B。ReadApp完成文件A并继续到B。它看到文件A处于打开状态并继续到C。在ReadApp读取同一文件时,WriteApp不写入非常重要,反之亦然。它们是不同的过程。

    11 回复  |  直到 5 年前
        1
  •  119
  •   Tom Hawtin - tackline    6 年前

    FileChannel.lock可能就是您想要的。

    try (
        FileInputStream in = new FileInputStream(file);
        java.nio.channels.FileLock lock = in.getChannel().lock();
        Reader reader = new InputStreamReader(in, charset)
    ) {
        ...
    }
    

    (免责声明:代码未编译,当然也未测试。)

    请注意中标题为“平台依赖项”的部分 API doc for FileLock .

        2
  •  63
  •   bozu ayengin    11 年前

    java.io 包,而使用 java.nio 包裹后者有一个 FileLock 班您可以将锁应用于 FileChannel .

     try {
            // Get a file channel for the file
            File file = new File("filename");
            FileChannel channel = new RandomAccessFile(file, "rw").getChannel();
    
            // Use the file channel to create a lock on the file.
            // This method blocks until it can retrieve the lock.
            FileLock lock = channel.lock();
    
            /*
               use channel.lock OR channel.tryLock();
            */
    
            // Try acquiring the lock without blocking. This method returns
            // null or throws an exception if the file is already locked.
            try {
                lock = channel.tryLock();
            } catch (OverlappingFileLockException e) {
                // File is already locked in this thread or virtual machine
            }
    
            // Release the lock - if it is not null!
            if( lock != null ) {
                lock.release();
            }
    
            // Close the file
            channel.close();
        } catch (Exception e) {
        }
    
        3
  •  17
  •   roottraveller    8 年前

    如果你能用 Java NIO ( JDK 1.4或更高版本 ),那么我想你在找 java.nio.channels.FileChannel.lock()

    FileChannel.lock()

        4
  •  8
  •   Matt    17 年前
        5
  •  5
  •   pkaeding    17 年前

    这可能不是你想要的,但是为了从另一个角度解决问题。。。。

    这两个Java进程是否希望在同一个应用程序中访问同一个文件?也许您可以通过一个同步的方法(或者更好的是,使用 JSR-166

        6
  •  3
  •   Kevin Day    17 年前

    使用RandomAccessFile,获取其通道,然后调用lock()。输入或输出流提供的通道没有足够的权限正确锁定。确保在finally块中调用unlock()(关闭文件并不一定会释放锁)。

        7
  •  1
  •   Ajay Kumar    8 年前

    下面是一个示例代码片段,用于锁定文件,直到JVM完成其处理。

     public static void main(String[] args) throws InterruptedException {
        File file = new File(FILE_FULL_PATH_NAME);
        RandomAccessFile in = null;
        try {
            in = new RandomAccessFile(file, "rw");
            FileLock lock = in.getChannel().lock();
            try {
    
                while (in.read() != -1) {
                    System.out.println(in.readLine());
                }
            } finally {
                lock.release();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    }
    
        8
  •  0
  •   Vamsi    5 年前

    如果要使用winscp或ftp进行传输,请在unix中使用此选项:

    public static void isFileReady(File entry) throws Exception {
            long realFileSize = entry.length();
            long currentFileSize = 0;
            do {
                try (FileInputStream fis = new FileInputStream(entry);) {
                    currentFileSize = 0;
                    while (fis.available() > 0) {
                        byte[] b = new byte[1024];
                        int nResult = fis.read(b);
                        currentFileSize += nResult;
                        if (nResult == -1)
                            break;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println("currentFileSize=" + currentFileSize + ", realFileSize=" + realFileSize);
            } while (currentFileSize != realFileSize);
        }