可能的重复:
如何使用 java 锁定文件(如果可能)
我有两个进程调用两个修改相同文本文件的 Java 程序。我注意到文本文件的内容缺少数据。我怀疑当一个 java 程序获取到文本文件的写入流时,我认为它会阻止另一个 java 程序修改它(就像当你打开一个文件时,你不能删除那个文件)。除了数据库,有没有办法解决这个问题?(不是说db解决方案不干净或不优雅,只是我们在操作这个文本文件时写了很多代码)
编辑
事实证明,我针对这个问题犯了一个错误。我的文本文件中的数据丢失的原因是,
ProcessA: 继续将数据行添加到文本文件中
ProcessB: 在开始时,将文本字段的所有行加载到一个List. 然后操作该列表的包含。最后,ProcessB将列表写回,替换文本文件的包含。
这在顺序过程中效果很好。但是当一起运行时,如果ProcessA向文件中添加数据,在ProcessB操作期间List,那么当ProcessB写List回时,无论ProcessA添加什么,都会被覆盖。所以我最初的想法是在ProcessB写List回之前,同步文本文件和List. 所以当我写List回时,它将包含所有内容。所以这是我的努力
public void synchronizeFile(){
try {
File file = new File("path/to/file/that/both/A/and/B/write/to");
FileChannel channel = new RandomAccessFile(file, "rw").getChannel();
FileLock lock = channel.lock(); //Lock the file. Block until release the lock
List<PackageLog> tempList = readAllLogs(file);
if(tempList.size() > logList.size()){
//data are in corrupted state. Synchronized them.
for(PackageLog pl : tempList){
if(!pl.equals(lookUp(pl.getPackageLabel().getPackageId(), pl.getPackageLabel().getTransactionId()))){
logList.add(pl);
}
}
}
lock.release(); //Release the file
channel.close();
} catch (IOException e) {
logger.error("IOException: ", e);
}
}
Run Code Online (Sandbox Code Playgroud)
所以logList是当前列表ProcessB想写出来。所以在写出之前,我读取文件并将数据存储到 中tempList,如果tempList和logList不一样,同步它们。问题是,在这一点上,ProcessA和ProcessB当前都访问该文件,因此当我尝试锁定文件并从中读取时List<PackageLog> tempList = readAllLogs(file);,我要么得到OverlappingFileLockException,要么java.io.IOException: The process cannot access the file because another process has locked a portion of the file. 请帮我解决这个问题:(
EDIT2:我对锁的理解
public static void main(String[] args){
File file = new File("C:\\dev\\harry\\data.txt");
FileReader fileReader = null;
BufferedReader bufferedReader = null;
FileChannel channel = null;
FileLock lock = null;
try{
channel = new RandomAccessFile(file, "rw").getChannel();
lock = channel.lock();
fileReader = new FileReader(file);
bufferedReader = new BufferedReader(fileReader);
String data;
while((data = bufferedReader.readLine()) != null){
System.out.println(data);
}
}catch(IOException e){
e.printStackTrace();
}finally{
try {
lock.release();
channel.close();
if(bufferedReader != null) bufferedReader.close();
if(fileReader != null) fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我收到了这个错误 IOException: The process cannot access the file because another process has locked a portion of the file
因此,您可以使用 Vineet Reynolds 在他的评论中建议的方法。
如果这两个进程实际上只是同一应用程序中的单独线程,那么您可以在某处设置一个标志来指示文件已打开。
如果它是两个独立的应用程序/进程,则底层文件系统应该锁定文件。当您从输出流中收到 I/O 错误时,您应该能够在该错误周围包装一个 try/catch 块,然后将您的应用程序设置为稍后重试,或者设置您的特定应用程序所需的任何行为。
文件并不是真正设计为由多个应用程序同时写入的。如果您可以描述为什么要从多个进程同时写入文件,则可能会建议其他解决方案。
最近编辑后的更新:好的,所以您至少需要 3 个文件才能完成您所说的操作。您绝对不能尝试同时读取/写入数据到单个文件。您的三个文件是:
ProcessB的循环:
ProcessA的循环:
| 归档时间: |
|
| 查看次数: |
23651 次 |
| 最近记录: |