繁体   English   中英

如何使用 FileInputStream 和 FileOutputStream 锁定文件以读取和写入同一文件

[英]How to lock a file for read and write to same file using FileInputStream and FileOutputStream

我有一个进程将锁定文本文件并以随机时间间隔用新的文本字符串覆盖同一个文件。 而且我写了另一个进程,一个WatchService,它监听同一个目录的变化,然后锁定文件并读取文件的内容。 我相信锁定文件在这里很重要,因为我想确保一次只有一个进程可以读/写同一个进程。

该代码仅成功运行以锁定文件并将内容写入文件,WatchService 能够检测到目录中的更改,但无法锁定和读取内容。

根据日志,它说The process cannot access the file because another process has locked a portion of the file但我已明确编写channel.close()以关闭文件通道。

我做错了什么? 我误会了什么?

更新:根据下面的建议,我已经用tryLock替换了lock并释放了锁,但它仍然无法运行lock = channel.tryLock(); 在 WatchFile class 中。 由于它不会产生任何错误,因此我只是通过System.out.println发现了这一点,以查看代码卡在哪里。

// Lock file and write 
public static void WriteTo throws IOException{
    String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss").withZone(ZoneId.of("Asia/Hong_Kong")));
    FileOutputStream fos = null;
    FileChannel channel = null;
    FileLock lock = null;
    try{
        fos = new FileOutputStream("C:\\Testing\\newTimestamp.txt");
        channel = fos.getChannel();
        lock = channel.tryLock();
        // write to channel
        byte[] mybytes = order_str.getBytes();
        fos.write(mybytes);
        System.out.println("File Successfully Written !");
    } catch(NonWritableChannelException e) {
        e.printStackTrace();
    } finally {
        lock.release();
        channel.close();
        fos.close();
    }
}
// Lock file and read contents
private static class WatchFile implements Runnable{
    public WatchFile(){

    }

    public void run() { 
        try {
            System.out.println("2. WatchService Started Running @ " + LocalDateTime.now() + " !!!");
            Path path = Paths.get("C:\\Testing");
            path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE,StandardWatchEventKinds.ENTRY_MODIFY,StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.OVERFLOW);
            WatchKey key;
            while((key = watchService.take()) != null) {
                for(WatchEvent<?> event: key.pollEvents()) {
                    System.out.println("Event time: "+ LocalDateTime.now() + ". Event kind:" + event.kind() + ". File affected: " + event.context() +".");
                    // only register 
                    final Path changed = (Path) event.context();
                    System.out.println("Changed: " + event.context());
                    if(changed.endsWith("newTimestamp.txt") && event.kind() == StandardWatchEventKinds.ENTRY_MODIFY) {

                        String line;
                        FileInputStream fis = null;
                        FileChannel channel = null;
                        FileLock lock = null;
                        BufferedReader br = null;
                        try {
                            fis = new FileInputStream("C:\\Testing\\newTimestamp.txt");
                            channel = fis.getChannel();
                            lock = channel.tryLock();
                            br =  new BufferedReader(new InputStreamReader(fis));
                            while((line = br.readLine()) != null) {
                                // process string
                            }
                        } catch(IOException e) {
                            e.printStackTrace();
                        } finally {
                            if (br != null) {
                                try {
                                    br.close();
                                    lock.release();
                                    channel.close();
                                    fis.close();
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                }
                key.reset();
            }

        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        } 
    }
}

错误:

java.io.IOException: The process cannot access the file because another process has locked a portion of the file
    at java.base/java.io.FileInputStream.readBytes(Native Method)
    at java.base/java.io.FileInputStream.read(FileInputStream.java:279)
    at java.base/sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
    at java.base/sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
    at java.base/sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
    at java.base/java.io.InputStreamReader.read(InputStreamReader.java:185)
    at java.base/java.io.BufferedReader.fill(BufferedReader.java:161)
    at java.base/java.io.BufferedReader.readLine(BufferedReader.java:326)
    at java.base/java.io.BufferedReader.readLine(BufferedReader.java:392)

我猜你错过了释放锁。 lock.release() 或 lock.close()

使用 channel.tryLock() 代替 channel.lock() 会更合适

PS一定要检查。 是否获得锁:

一个锁 object 代表新获得的锁,或者 null 如果由于另一个程序持有重叠的位置而无法获得锁

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM