MappedByteBuffer 写入文件不起作用

MappedByteBuffer writing to file not working

我很难理解 MappedByteBuffer 的读写。 这是我拥有的 class,它读取本地文件的内容并假设要反转其内容。我正在使用 java 版本 8.

public class MappedByteBufferExample {
public static void main(String[] args) {
    try (RandomAccessFile file = new RandomAccessFile("resources\MappedByteBufferExample.txt", "rw");
            FileChannel fileChannel = file.getChannel();) {
        long size = fileChannel.size();
        MappedByteBuffer mappedBuffer = fileChannel.map(MapMode.READ_WRITE, 0, size);

        System.out.println("Text from File : -----");
        while (mappedBuffer.remaining() > 0) {
            System.out.print((char) mappedBuffer.get());
        }
        System.out.println("\n");

        for (int index = 0; index < (mappedBuffer.limit() / 2); index++) {
            byte b1 = mappedBuffer.get(index);
            byte b2 = mappedBuffer.get(mappedBuffer.limit() - index - 1);
            mappedBuffer.put(index, b2);
            mappedBuffer.put(mappedBuffer.limit() - index - 1, b1);
        }
        //mappedBuffer.force();  I tried with this but no change in result.
        //mappedBuffer.load(); I tried with this but no change in result.
        mappedBuffer.load();
        mappedBuffer.flip();
        System.out.println("Text Reversed : -----");
        while (mappedBuffer.remaining() > 0) {
            System.out.print((char) mappedBuffer.get());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}}

文件内容是——玫瑰红了!
执行此文件到控制台的输出是:

文件中的文本:-----

玫瑰是红的!

文本反转:-----

!deR 时代 sesoR

但是文件内容没有改变。 第二次执行这个程序时,控制台的输出是:

文件中的文本:-----

!deR 时代 sesoR

文本反转:-----

玫瑰是红的!

文件内容仍未改变。 我一次尝试了 load() 和 force() 方法,但结果没有变化 这是我的问题:

1)为什么本地文件的内容没有改变?

2) 本程序需要做哪些改动才能使数据写入文件?

3) Why/How MappedByteBuffer 在第二次迭代时读取了反转的文本,尽管文件内容没有反转?

文件内容已更改。普通的编辑器(如 notepad++ 或 eclipse)不会注释更改,因为使用 RandomAccessFile 不会更改文件日期时间。但是,如果您真的在 运行 之后手动重新加载文件,您应该会看到更改。

既然你的实际问题已经解决了,一些备注:

  • 从Java 1.7开始,你不需要RandomAccessFile绕路去打开一个FileChannel
  • Charset API 允许您将 ByteBuffer 的内容正确地 转换为字符(将 byte 转换为char 仅对当前 Windows 代码页的一个子集是正确的)并且不需要手动遍历字节
  • 可以通过使用两个索引直接编写交换循环,而不是在每次迭代中重新计算第二个索引(和循环的结束索引)

将这些点放在一起,简化的变体如下所示:

try(FileChannel fileChannel = FileChannel.open(
        Paths.get("resources\MappedByteBufferExample.txt"),
        StandardOpenOption.READ, StandardOpenOption.WRITE)) {
    long size = fileChannel.size();
    MappedByteBuffer mappedBuffer = fileChannel.map(MapMode.READ_WRITE, 0, size);

    System.out.println("Text from File : -----");
    System.out.append(Charset.defaultCharset().decode(mappedBuffer)).println("\n");

    for(int index1 = 0, index2=(int)size-1; index1<index2; index1++, index2--) {
        byte b1 = mappedBuffer.get(index1), b2 = mappedBuffer.get(index2);
        mappedBuffer.put(index1, b2).put(index2, b1);
    }
    mappedBuffer.force();
    mappedBuffer.flip();
    System.out.println("Text Reversed : -----");
    System.out.append(Charset.defaultCharset().decode(mappedBuffer)).println("\n");
} catch (IOException e) {
    e.printStackTrace();
}

请记住,读取循环将始终显示更改后的状态,无论它是否已写入文件。所以 force() 是放在读取循环之前还是放在块的末尾都没有关系。