Java:如何处理试图修改同一个文件的两个进程

标签 java io

<分区>

Possible Duplicate:
How can I lock a file using java (if possible)

我有两个进程调用两个修改同一个文本文件的 Java 程序。我注意到文本文件的内容缺少数据。我怀疑当一个 java 程序获取到文本文件的写入流时,我认为它会阻止另一个 java 程序修改它(比如当你打开一个文件时,你不能删除该文件)。除了数据库之外,有没有办法解决这个问题? (并不是说 db 解决方案不干净或不优雅,只是我们在操作这个文本文件时写了很多代码)

编辑

原来我针对问题的定位是错误的。我的文本文件中的数据丢失的原因是,

ProcessA : 不断向文本文件中添加数据行

ProcessB : 开始时,将文本字段的所有行加载到 List 中.然后它操纵该列表的包含。最后,ProcessB写回列表,替换文本文件的内容。

这在顺序过程中非常有效。但是一起跑的时候,如果ProcessAProcessB期间向文件添加数据操纵 List , 然后当 ProcessBList退出,无论如何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); 
    }
}

所以 logListProcessB 的当前列表想写出来。所以在写出之前,我读取文件并将数据存储到 tempList 中, 如果 tempListlogList不一样,同步它们。问题是在这一点上,ProcessAProcessB当前正在访问该文件,所以当我尝试锁定该文件并从中读取时 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:我对 Lock 的理解

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();
        }
    }
}

我得到了这个错误 IOException: The process cannot access the file because another process has locked a portion of the file

最佳答案

因此,您可以使用 Vineet Reynolds 在他的评论中建议的方法。

如果这两个进程实际上只是同一应用程序中的独立线程,那么您可以在某处设置一个标志以指示该文件已打开。

如果它是两个独立的应用程序/进程,底层文件系统应该锁定文件。当您从输出流中收到 I/O 错误时,您应该能够围绕它包装一个 try/catch block ,然后将您的应用程序设置为稍后重试,或者为您的特定应用程序设置任何所需的行为。

文件并非真正设计为由多个应用程序同时写入。如果您可以描述为什么要从多个进程同时写入一个文件,可能会有其他建议的解决方案。


最近编辑后的更新: 好的,所以你至少需要 3 个文件来完成你所说的。您绝对不能尝试同时将数据读/写到单个文件。您的三个文件是:

  1. ProcessA 将新数据/传入数据转储到的文件
  2. ProcessB 当前正在处理的文件
  3. 保存 ProcessB 输出的最终“输出”文件。

ProcessB 的循环:

  • 获取文件#2 中的任何数据,对其进行处理,并将输出写入文件#3
  • 删除文件#2
  • 重复

ProcessA 的循环:

  • 将所有新的传入数据写入文件#1
  • 定期检查文件 #2 是否存在
  • 当 ProcessB 删除文件#2 时,ProcessA 应该停止写入文件#1,将文件#1 重命名为文件#2
  • 开始一个新文件#1
  • 重复

关于Java:如何处理试图修改同一个文件的两个进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6332406/

相关文章:

java - iText 最新 Maven 依赖

java - 如何检查扫描仪是否已关闭

java - Java 如何处理整数下溢和上溢以及如何检查它?

java - 在java中连接到共享驱动器

python - 如何解析下面的 .txt 文件?

c++ - 写入二进制 mangles 数据

java - MapReduce 中的 N 轮减少

java - 计时器是最适合用于文件调度程序的吗?

io - 有没有办法在不重新分配的情况下使用 std::io::Write 写入内存缓冲区?

java - 客户端断开连接时线程异常