[英]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.