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

如何使用java锁定文件(如果可能),java,file-io,Java,File Io,我有一个Java进程,它使用FileReader打开一个文件。如何防止另一个(Java)进程打开此文件,或者至少通知第二个进程该文件已打开?如果文件已打开(这解决了我的问题),这会自动使第二个进程出现异常吗?还是必须在第一个进程中使用某种标志或参数显式打开它 澄清: 我有一个Java应用程序,它列出一个文件夹,并打开列表中的每个文件进行处理。它一个接一个地处理每个文件。每个文件的处理包括读取文件和根据内容进行计算,大约需要2分钟。我还有另一个Java应用程序,它也做同样的事情,但却在文件上写。我

我有一个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不写入非常重要,反之亦然。它们是不同的进程。

如果您可以使用Java NIO(JDK 1.4或更高版本),那么我认为您正在寻找
Java.NIO.channels.FileChannel.lock()


如果您可以使用JavaNIO(JDK1.4或更高版本),那么我认为您正在寻找
Java.NIO.channels.FileChannel.lock()


一起使用与

文件通道一起使用。锁定可能是您想要的

try (
    FileInputStream in = new FileInputStream(file);
    java.nio.channels.FileLock lock = in.getChannel().lock();
    Reader reader = new InputStreamReader(in, charset)
) {
    ...
}
(免责声明:代码未编译,当然也未测试。)


请注意。

FileChannel.lock中标题为“平台依赖项”的部分可能就是您想要的

try (
    FileInputStream in = new FileInputStream(file);
    java.nio.channels.FileLock lock = in.getChannel().lock();
    Reader reader = new InputStreamReader(in, charset)
) {
    ...
}
(免责声明:代码未编译,当然也未测试。)


请注意。

中标题为“平台依赖项”的部分使用RandomAccessFile,获取其频道,然后调用lock()。输入或输出流提供的通道没有足够的权限正确锁定。确保在finally块中调用unlock()(关闭文件不一定会解除锁定)。

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

这可能不是您要寻找的,而是为了从另一个角度解决问题


这两个Java进程是否希望在同一个应用程序中访问同一个文件?也许您可以通过一个同步的方法(或者更好的是,使用)过滤对文件的所有访问?这样,您就可以控制对文件的访问,甚至可以对访问请求进行排队。

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


这两个Java进程是否希望在同一个应用程序中访问同一个文件?也许您可以通过一个同步的方法(或者更好的是,使用)过滤对文件的所有访问?这样,您就可以控制对文件的访问,甚至可以对访问请求进行排队。

不要使用
java.io
包中的类,而是使用
java.nio
包。后者有一个
FileLock
类。您可以对
文件通道
应用锁

 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) {
    }

不要使用
java.io
包中的类,而是使用
java.nio
包。后者有一个
FileLock
类。您可以对
文件通道
应用锁

 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) {
    }

下面是一个示例代码片段,用于锁定文件,直到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();
        }
    }

}

下面是一个示例代码片段,用于锁定文件,直到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();
        }
    }

}

如果要使用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);
    }

如果要使用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);
    }

您是指进程(两个JVM)还是线程(相同JVM)中的“进程”。对答案的影响是至关重要的。检查这里显示解决方案的示例代码:您指的是进程(两个JVM)中的“进程”还是线程(同一个JVM)。对答案的影响是至关重要的。请检查显示解决方案的示例代码:可能。取决于OP对“过程”的定义。“文件锁代表整个Java虚拟机。它们不适合控制同一虚拟机内多个线程对文件的访问。”@Stu:我知道你很久以前就回答过这个问题,但我希望您能详细说明您所说的
文件锁代表整个Java虚拟机持有的意思。它们不适用于控制同一虚拟机内多个线程对文件的访问
@Harry他从文档中引用:这意味着它对线程不可见,但会影响其他进程。@Harry:为了给这些necro注释添加更多内容,假设您使用Java为Tomcat网站提供服务。您可能有很多线程,每个线程都为来自web浏览器的一个请求提供服务。但是,它们都控制着相同的文件锁定机制,就像厨房里有太多厨师一样。一个请求可能在第二个请求的中间完成,并且当你还在某个中间时,你的文件突然“解锁”,然后像CrOnWork之类的其他进程可能锁定它,然后你意外地丢失了你的锁,并且你的请求无法完成……也许。取决于OP对“过程”的定义。“文件锁代表整个Java虚拟机。它们不适合控制同一虚拟机内多个线程对文件的访问。”@Stu:我知道你很久以前就回答过这个问题,但是