簡體   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