【问题标题】:Cannot access file because being used无法访问文件,因为正在使用
【发布时间】:2017-03-19 08:28:00
【问题描述】:

我正在为我的 java 程序编写一个记录器(以 csv 格式)。 记录器工作正常,但我遇到了一个问题。

当我尝试写入文件并同时打开文件时程序会崩溃,这听起来很合乎逻辑。 当我这样做时,我得到了那个异常:“该进程无法访问该文件,因为它正在被另一个进程使用”。

我的问题是,即使有人打开了文件,是否还能继续写?

谢谢。

更新:

我想我解决了这个问题。 每次写入文件后(使用 bufferedWriter 和 FileWriter),我都会调用一个 close() 函数来关闭 bufferedWriter 和 FileWriter。

我更改了 close() 函数: 1.新增fileChannel和FileLock。 2. 忽略 bw.close();

不关闭bufferWriter(bw)可以吗,以后会不会有什么问题?

private void close() throws IOException {
    RandomAccessFile rf;
    rf = new RandomAccessFile(file, "rw");
    fileChannel = rf.getChannel();
    lock = fileChannel.lock();
    try {
        if (bw != null) {
            //    bw.close();  The line i ignored.
            bw = null;
        }
        if (fw != null) {
            fw.close();
            fw = null;
        }
    } catch (IOException ex) {
        ex.printStackTrace();
    }

    lock.release();

}

更新 2: 现在我发现如果我将功能更改为那个(关闭更改为刷新),它的工作原理:

   private void close()  {
    try {
        if (bw != null) {
            bw.flush(); 
            bw = null;
        }
        if (fw != null) {
            fw.flush();
            fw = null;
        }
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

最好的选择是什么?

【问题讨论】:

  • 请出示您的代码。

标签: java file csv exception


【解决方案1】:

解决问题:边写边尝试打开:

  • 如果要固定数据,可以复制文件(通过shell),然后读取;

  • 如果您甚至想要将来写入的数据,则必须保持相同的输出:尝试将正常输出重定向到您可以存储和读取的内容。

也许存在一些库。它看起来像 tee 和 tpipe。

例如: Could I duplicate or intercept an output stream in Java?

  • 要将 log4j 重定向到您想要的,请参见以下示例:

How do I redirect log4j output to my HttpServletResponse output stream?

【讨论】:

    【解决方案2】:

    即使有其他东西打开了文件,是否还有继续写入的方法?

    Java 中没有。

    要写入文件,您必须先打开它。如果您因为操作系统不允许而无法打开它......因为其他东西已经打开它......那么您就无法达到可以编写它的地步。

    在这种情况下,您应该考虑打开不同的日志文件。


    请注意,这种情况发生在 Windows 中,因为 Java 遵循正常的 Window 实践并默认使用排他(强制)锁定打开文件。缺少更改 Java ......以及打开此类文件的所有其他 Windows 应用程序......你被卡住了。


    更新

    事实证明,可能有办法。

    1. 阅读此问答:https://stackoverflow.com/a/22648514/139985
    2. 按照描述使用FileChannel.open,但使用允许您在不禁止其他编写者的情况下编写的标志。例如

         FileChannel.open(path, WRITE)
      

         FileChannel.open(path, WRITE, APPEND)
      

      诀窍是您不需要任何 NOSHARE_* 选项。

    警告:我还没有尝试过。

    【讨论】:

      【解决方案3】:

      正如@guillaume 所说,您可以使用 log4j 之类的库。

      但如果您想用 Java 实现您的解决方案,您可以使用观察者模式并异步编写日志。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-03-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-15
        相关资源
        最近更新 更多