简体   繁体   English

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

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

I have a process that will lock the text file and write over the same file with a new text string at random time intervals.我有一个进程将锁定文本文件并以随机时间间隔用新的文本字符串覆盖同一个文件。 And I have written another process, a WatchService that listens to changes in the same directory and then locks the file and reads the content of the file.而且我写了另一个进程,一个WatchService,它监听同一个目录的变化,然后锁定文件并读取文件的内容。 I believe Locking the file is important here, as I want to make sure only one process can either read/write to the same at one time.我相信锁定文件在这里很重要,因为我想确保一次只有一个进程可以读/写同一个进程。

The code only runs successfully to lock the file and write contents to the file and the WatchService is able to detect changes in the directory but it fails to lock and read the content.该代码仅成功运行以锁定文件并将内容写入文件,WatchService 能够检测到目录中的更改,但无法锁定和读取内容。

Based on the logs, it says that The process cannot access the file because another process has locked a portion of the file but I have explicitly written channel.close() to close the file channel already.根据日志,它说The process cannot access the file because another process has locked a portion of the file但我已明确编写channel.close()以关闭文件通道。

What have I done wrong?我做错了什么? What did I misunderstand?我误会了什么?

UPDATE: per suggestion below, I have replaced lock with tryLock and release the lock too but it's still not able to run past the line lock = channel.tryLock();更新:根据下面的建议,我已经用tryLock替换了lock并释放了锁,但它仍然无法运行lock = channel.tryLock(); in the WatchFile class.在 WatchFile class 中。 Since it doesn't generate any error, I only found out about this through System.out.println to see where the code got stuck.由于它不会产生任何错误,因此我只是通过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();
        } 
    }
}

Error:错误:

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)

I guess you missed to release of the lock.我猜你错过了释放锁。 lock.release() OR lock.close() lock.release() 或 lock.close()

And it would be more suitable to use channel.tryLock() instead channel.lock()使用 channel.tryLock() 代替 channel.lock() 会更合适

PS be sure to check. PS一定要检查。 Is lock acquired or not:是否获得锁:

A lock object representing the newly-acquired lock, or null if the lock could not be acquired because another program holds an overlapping loc一个锁 object 代表新获得的锁,或者 null 如果由于另一个程序持有重叠的位置而无法获得锁

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

相关问题 FileInputStream 和 FileOutputStream:读写同一个文件 - FileInputStream and FileOutputStream: Read and write to the same file FileInputStream 和 FileOutputStream 到同一个文件:read() 是否保证看到“之前发生过”的所有 write()? - FileInputStream and FileOutputStream to the same file: Is a read() guaranteed to see all write()s that "happened before"? Java:同一文件上的FileOutputStream和FileInputStream - Java: FileOutputStream and FileInputStream together on the same file 使用 FileInputStream 和 FileOutputStream 读写同一个文件 - Reading and writing into the same file with FileInputStream and FileOutputStream FileOutputStream创建一个文件,但是FileInputStream - FileOutputStream creates a file, but FileInputStream 使用FileInputStream和FileOutputStream上传大文件 - Large file upload using FileInputStream and FileOutputStream 如何:使用 FileOutputStream 编写文件? - How To : Write a File with FileOutputStream? 如何使用FileOutputStream在文件中写入整数? - How to write an integer in a file using FileOutputStream? FileInputStream.read()与FileOutputStream.write() - FileInputStream.read() vs FileOutputStream.write() Java Inventory - 如何使用FileInputStream读取文件? - Java Inventory - How to read a file using FileInputStream?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM