java nio RandomAccessFile FileChannel通道实现文件的读写 乱码问题分析

该代码示例展示了如何使用RandomAccessFile和FileChannel进行文件的读写操作,包括指针同步、从文件末尾追加和开头覆盖内容。同时,提到了写入字节覆盖多字节字符可能导致的乱码问题以及ByteBuffer在读写模式间的转换方法。
摘要由CSDN通过智能技术生成

通过一个通道及缓存区完成文件的读 写操作,通过本例代码验证了:

* 1 RandomAccessFile的指针与FileChannel 的指针是同步更新的,结果是一致的.

* 2 channel.position(channel.size()):从文件末尾追加内容,channel.position(0):从文件开头覆盖内容,可以指定0到channel.size() 之间的任意值以完成文件读写定位.

* 3 写入文件时,RandomAccessFile是以字节为单位写入,写入的字节覆盖源文件中多字节字符的部分字节后,文件将出现乱码.

* 4 channel.read(buffer) 对buffer来说是写入模式,channel.write(buffer)是读取模式,需要转换flip.

* 5 从buffer中读取数据时有两种方式,第二种方式可以有效避免buffer中的无效字节(0字节),详情见代码

 static void readWriteFile() throws IOException {

        try (  //可读写的通道
                RandomAccessFile randomAccessFile = new RandomAccessFile(fileName, "rw");
                FileChannel channel = randomAccessFile.getChannel()){

            System.out.println("0 文件读写指针:" + randomAccessFile.getFilePointer());
            System.out.println("0 channel指针:" + channel.position());
            ByteBuffer buffer = ByteBuffer.allocate(1024);

            System.out.println("读取数据:");
            int size = 0;
            //读取数据时,buffer是写入模式
            while ((size = channel.read(buffer)) > 0) {
                System.out.println("\t第一次读取到数据,字节数:" + size);
                //取出buffer中的数据,buffer应该是读取模式,需要转换
                buffer.flip();

                System.out.println("\t提取数据方式一(buffer中的无效数据会转为空字符):");
                byte[] array = buffer.array();
                String s = new String(array, Charset.defaultCharset());
                System.out.println(s);

                System.out.println("\t提取数据方式二(仅转换了buffer中有效的部分):");
                CharBuffer charBuffer = Charset.defaultCharset().decode(buffer);
                System.out.println(charBuffer);
                buffer.clear();
            }

            System.out.println();
            System.out.println("1 文件读写指针:" + randomAccessFile.getFilePointer());
            System.out.println("1 channel指针:" + channel.position());
            /**
             * 从文件头部写入数据(覆盖现有的数据)
             * 有个很有意思的地方:写入的文件会出现乱码,因为覆盖数据是以字节为单位进行的,
             * 当原文件中的多字节码字符其中的部分字节被覆盖时,就出现了乱码
             */
            channel.position(0);
            //从文件末尾追加数据
            // channel.position(channel.size());
            System.out.println("写入数据:");
            //定义要写入的字节数组
            byte[] bs = "aaa123".getBytes(StandardCharsets.UTF_8);
            System.out.println(new String(bs, Charset.defaultCharset()));

            buffer.clear();
            buffer.put(bs);
            //写入文件时,相当于从buffer中读数据,所以,需要 flip 一下.
            buffer.flip();
            channel.write(buffer);

            System.out.println("2 文件读写指针:" + randomAccessFile.getFilePointer());
            System.out.println("2 channel指针:" + channel.position());
        }
    }

文件中的内容为:

Hello!好好学习,天天向上!
Very Good !

从文件头部写入以下内容时,文件正常无乱码,6个字节正好替换了原文件中的 Hello!

aaa123

从文件头部写入以下内容时,文件出现乱码!

因为写入内容有7个字节,从头覆盖时,会将第一个"好"的第一个字节替换成4,导致"好"字编码失败,因而出现乱码.

aaa1234

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值