Java:如何处理两个尝试修改同一文件的进程 [英] Java: how to handle two process trying to modify the same file

查看:218
本文介绍了Java:如何处理两个尝试修改同一文件的进程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


可能重复:

如何使用java锁定文件(如果可能)

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

I have two process that invoke two Java programs that modifying the same text file. I notice the content of the text file is missing data. I suspect that when one java program obtain the write stream to the text file, I think it block the other java program from modifying it(like when you have a file open, you cant delete that file). Is there a way to work around this other than database? (not to say that db solution is not clean or elegant, just that we wrote lot of codes in manipulating this text file)

编辑

事实证明我针对这个问题犯了一个错误。我的文本文件中缺少数据的原因是,

It turns out that I made a mistake targeting the problem. The reason why, data in my text file is missing is because,

ProcessA :继续添加数据行文本文件

ProcessA: keep add rows of data to the text file

ProcessB :在开头,将文本字段的所有行加载到列表。然后它操纵该列表的包含。最后, ProcessB 将列表写回,替换文本文件的包含。

ProcessB: at the beginning, load all the rows of the text field into a List. It is then manipulate the contains of that list. At the end, ProcessB write the list back out, replacing the contain of the text file.

这项工作在顺序过程中非常出色。但是当一起运行时,如果 ProcessA 将数据添加到文件中,那么在 ProcessB 期间操纵列表,然后当 ProcessB 写回列表时,无论 ProcessA 只需添加,将被覆盖。所以我最初的想法是在 ProcessB 之前写出 List 退出,同步文本文件和<$ c之间的数据$ C>列表。因此,当我写回 List 时,它将包含所有内容。所以这是我的努力

This work great in sequential process. But when running together, if ProcessA adding data to the file, during the time ProcessB manipulating the List, then when ProcessB write the List back out, whatever ProcessA just add, will be overrided. So my initial thought is before ProcessB write the List back out, sync the data between text file and the List. So when I write the List back out, it will contains everything. so here is my effort

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

所以 logList ProcessB 想要写出的当前列表。所以在写出之前,我读取文件并将数据存储到 tempList 中,如果 tempList logList 不一样,同步它们。问题是,此时, ProcessA ProcessB 当前都访问该文件,所以当我尝试锁定文件,并从中读取列表< PackageLog> tempList = readAllLogs(file); ,我得到 OverlappingFileLockException ,或者 java.io.IOException:进程无法访问该文件,因为另一个进程已锁定文件的一部分。请帮我解决这个问题:(

So logList is the current List that ProcessB want to write out. So before the write out, I read the file and store data into tempList, if tempList and logList are not the same, sync them. The problem is that at this point, both ProcessA and ProcessB currently access the file, so when I try to lock the file, and read from it List<PackageLog> tempList = readAllLogs(file);, I either get OverlappingFileLockException, or java.io.IOException: The process cannot access the file because another process has locked a portion of the file. Please please help me fix this problem :(

EDIT2 :我对Lock的理解

EDIT2: My understand of 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:进程无法访问该文件,因为另一个进程已锁定文件的一部分

推荐答案

所以,你可以使用Vineet Reynolds在他的评论中建议的方法。

So, you could use the method that Vineet Reynolds suggests in his comment.

如果这两个进程实际上只是同一个应用程序中的单独线程,那么你可以在某处设置一个标志来表明该文件是打开的。

If the two processes are actually just separate Threads within the same application, then you could set a flag somewhere to indicate that the file is open.

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

If it's two separate applications/processes altogether, the underlying filesystem should lock the files. When you get an I/O error from your output stream, you should be able to wrap a try/catch block around that, and then set your app up to retry later, or whatever the desired behavior is for your particular application.

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

Files aren't really designed to be written to simultaneously by multiple applications. If you can maybe describe why you want to write to a file simultaneously from multiple processes, there may be other solutions that could be suggested.

最近编辑后的更新:
好​​的,所以你需要至少3个文件来做你正在谈论的事情。您绝对不能尝试同时读取/写入单个文件的数据。您的三个文件是:

Updates after your recent edits: Ok, so you need at least 3 files to do what you're talking about. You definitely cannot try to read/write data to a single file concurrently. Your three files are:


  1. ProcessA将新/传入数据转储到

  2. 文件的文件ProcessB当前正在处理

  3. 一个保存ProcessB输出的最终输出文件。

ProcessB的循环:

ProcessB's loop:


  • 获取文件#2中的任何数据,处理它,并将输出写入文件#3

  • 删除文件#2

  • 重复

ProcessA的循环:

ProcessA's loop:


  • 将所有新的传入数据写入文件#1

  • 定期检查文件是否# 2存在

  • 当ProcessB删除文件#2时,ProcessA应该停止写入文件#1,将文件#1重命名为文件#2

  • 开始新文件#1

  • 重复

  • Write all new, incoming data to file#1
  • Periodically check to see if file#2 exists
  • When file#2 is deleted by ProcessB, then ProcessA should stop writing to file#1, rename file#1 to be file#2
  • Start a new file#1
  • Repeat

这篇关于Java:如何处理两个尝试修改同一文件的进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆