【问题标题】:Why BufferedWriter is not writing into the file over the opened FileChannel?为什么 BufferedWriter 不通过打开的 FileChannel 写入文件?
【发布时间】:2020-11-24 05:56:25
【问题描述】:

下面是我的代码。我能够成功读取文件。但无法使用 BufferedWriter 用替换的内容重新写入它。但可以使用 ByteBuffer 来完成。有什么建议请教我哪里出错了。

myFile.txt 内容:

Key1-Value1
Key2-Value2
Key3-Value3

Java 代码如下:

String fileAbsolutePath = "C:\\myPath\\myFile.txt";

        try {
            RandomAccessFile file = new RandomAccessFile(fileAbsolutePath, "rw");
            FileChannel fileChannel = file.getChannel();
            FileLock lock = fileChannel.lock();
            // read from the channel
            BufferedReader bufferedReader = new BufferedReader(Channels.newReader(fileChannel, "UTF-8"));
        List<String> filteredList = bufferedReader.lines().filter(line -> !line.contains("KEY1-VALUE1")).onClose(() -> {
            try {
                bufferedReader.close();
            } catch (IOException ex) {
                throw new UncheckedIOException(ex);
            }
        }).collect(Collectors.toList());
            fileChannel.truncate(0);
            BufferedWriter bufferedWriter = new BufferedWriter(Channels.newWriter(fileChannel, "UTF-8"));
            for (String string : list) {
                bufferedWriter.write(string);//does n't work
                bufferedWriter.newLine();
            }
            lock.release();
            file.close();
            fileChannel.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

ByteBuffer 部分有效:

ByteBuffer buff = null;
            for (int i = 0; i < filteredList.size(); i++) {
                buff = ByteBuffer.wrap(filteredList.get(i).concat("\n").getBytes(StandardCharsets.UTF_8));
                fileChannel.write(buff);
            }

挑战是在BufferedWriter的帮助下实现同样的目标

尝试使用资源后更新代码

try (RandomAccessFile file = new RandomAccessFile(fileAbsolutePath, "rw");
                FileChannel fileChannel = file.getChannel();
                FileLock lock = fileChannel.lock();
                BufferedReader bufferedReader = new BufferedReader(Channels.newReader(fileChannel, "UTF-8"));
                BufferedWriter bufferedWriter = new BufferedWriter(Channels.newWriter(fileChannel, "UTF-8"))) {

            // read from the channel
            List<String> list = bufferedReader.lines().filter(line -> !line.contains("Key1-Value1"))
                    .collect(Collectors.toList());
            fileChannel.truncate(0);
            list.forEach(item -> {
                try {
                    bufferedWriter.write(item.concat("\n"));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
            bufferedWriter.flush();
        }

【问题讨论】:

  • 快速提问,但您为什么不只使用 NIO? Files.write(path, list).
  • 请注意,您的代码存在资源泄漏,因为您没有使用 try-with-resources。
  • // TODO handle exception 首先。 e.printStacktrace();
  • @JoopEggen 完成。但也不例外。似乎代码的BufferedWriter部分无法访问打开的fileChannel
  • @Zabuzard 我需要锁定文件,因为有可能同时有其他进程访问该文件。 Files.write(路径,列表);抛出异常 java.io.IOException: 该进程无法访问该文件,因为另一个进程已锁定该文件的一部分

标签: java nio bufferedwriter filechannel java.nio.file


【解决方案1】:

您不会在最后刷新 BufferedWriter,这意味着它包含您希望写回的部分或全部行。在关闭通道之前添加一个 flush() 以确保缓冲区被写出:

bufferedWriter.flush();
lock.release();

理想情况下,您应该将try() 与资源一起使用,以便在适当的时间完全关闭您的所有文件。

【讨论】:

  • 实施了您的建议。请参阅标题“尝试使用资源后更新代码”下的问题描述代码获取线程“主”java.nio.channels.ClosedChannelException on using try-with-resources。我可能又做错了什么?
  • 有趣 - 您可以将 RandomAccessFile / FileChannel / FileLock 移动到 try() 并在最后删除 release / close / close,但看起来您将不得不离开 BufferedReader 和 BufferedWriter和 flush() 因为如果他们自动关闭它会弄乱通道。
  • flush() 和以前一样。让我试试把BufferedReader/Writer移出试试
  • 非常感谢! BufferedReader/Writer 移出 try() 工作正常!
猜你喜欢
  • 2014-02-08
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多