JAVA NIO(三):缓冲区的相互转换及中文乱码的解决方案
来源:互联网 发布:淘宝号不要了怎么注销 编辑:程序博客网 时间:2024/06/05 17:20
在Java IO中,Channel(通道)只能直接与ByteBuffer进行通信,这样我们可能会用ByteBuffer的视图来解决数据的转换问题,如将字符串转换为二进制缓冲区,整数缓冲区转换为二进制缓冲区,示例如下:
ByteBuffer buffer = ByteBuffer.allocate(100);// 获取缓冲区的视图,但与ByteBuffer的mark、position、limit互相独立CharBuffer charBuff = buffer.asCharBuffer();// 更容易进行字符操作charBuff.put("Hello, World!");// 创建输出通道WritableByteChannel outChannel = Channels.newChannel(System.out);// 写入缓冲区数据outChannel.write(byteBuf);outChannel.close();
采用上述的方法,会导致以下几个问题:
1. 难以控制字符与字节的转换过程;
2. 难以获取缓冲区的当前位置与剩余空间;
3. 难以控制缓冲区的阶段读取,如20-50,50-70;
在上面的例子中,我们将CharBuffer与ByteBuffer进行了转换,极大地简化了字符的操作行为,但可惜的是,字符依赖于系统编码(这里是UTF-8,每个字符占两个字节),写入的时候每个字符占两个字节,但读取的时候却不知道编码,最后导致出现乱码。
要解决上述的问题,只有自己控制字符与字节转换的过程,才能保证字符的输入与输出保持一致,如下:
// 创建输出通道WritableByteChannel outChannel = Channels.newChannel(System.out);String text = "你好,JAVA!";byte[] arr = text.getBytes("UTF-8");ByteBuffer byteBuf = ByteBuffer.wrap(arr);outChannel.write(byteBuf);outChannel.close();
使用上述的方法,优点是能保证字符的正确转换,但是很显然,效率太低了,还有更好的办法吗?
经过实测,通过字节转换的效率并不低,并且比CharBuffer放入字符串的速度高4-5倍,对比数据如下:
这里最有意思的地方在于,CharBuffer统一以两个字节存储一个字符,而ByteBuffer则依赖于编码,可能是两个字节,也可能是三个字节,最后导致512个字符,CharBuffer的limit为512,换算为ByteBuffer后为1024个字节,而直接用ByteBuffer存储字节则为1200(依赖于具体的字符,不定),如下:
关于乱码,如果是以CharBuffer放入的数据,因为没有对应的字符集解码器,必定是乱码,只有通过同样的CharBuufer方式读出,才能正确解决,所以在这里,char是一种数据存储格式,就如同long数据、int数据一样,并不是操作系统上对应的字符集,所以无法解析。尤其是文本编辑器提示“此文档包含当前文本编码无法处理的字符”,则可以断定是以字符数据格式进行存储,处理方式如下:
FileInputStream fis = new FileInputStream(file);FileChannel fc = fis.getChannel();ByteBuffer bbuf = ByteBuffer.allocateDirect(1024);long offset = 0;long nums = 0;while((nums = fc.read(bbuf, offset)) > 0) { // 一定要反转回到正确位置,CharBuffer视图是基于当前位置创建的 bbuf.flip(); // 以字符数据方式进行读取 CharBuffer cbuf = bbuf.asCharBuffer(); bbuf.clear(); offset = offset + nums;}fc.close();fis.close();
结论
- 一定要区分字符与字符数据,如果是操作系统上的字符,则可对应到文本编码,并有相应的字符集编码,而字符数据必定是二进制编码;
- 缓冲区存储的是字节(不是字符);
- 字符由多个字节组成,如果不能按照指定的顺序与数量读取所需的字节,必然出现乱码。
- JAVA NIO(三):缓冲区的相互转换及中文乱码的解决方案
- java NIO(三) 缓冲区
- Java编程中中文乱码问题的研究及解决方案
- java的中文乱码转换
- java中文乱码及解决方案
- JAVA中文乱码的一些解决方案!
- Java中文乱码问题的解决方案
- 孙鑫讲Java中文乱码问题的解决方案
- Java中文乱码问题的解决方案
- Java中文乱码问题的解决方案
- Java servlet解决中文乱码的解决方案
- 中文乱码的解决方案:
- 中文字符编码的相互转换(三)
- QString和string的相互转换及乱码处理
- Java NIO缓冲区(Buffer)的数据存取
- NIO缓冲区的基本概念
- jsp中中文出现乱码的原因及解决方案(Java中Unicode、编码的理解)
- Java常见的乱码问题及解决方案
- java 中的接口和抽象类的异同
- docker下gdb调试断点不停
- 数据结构-树 总结
- Android Studio 开发之NDK混合开发的应用
- NoSQL
- JAVA NIO(三):缓冲区的相互转换及中文乱码的解决方案
- JVM垃圾回收算法
- SequoiaDB备份与恢复
- Linux 安装软件的几种方式
- C# 并行编程 之 命令式任务并行 (.Net Framework 4.0)
- UVA 10075 Airlines (Floyd + 数学转换)
- CGlib无入侵代理入门使用
- 341353
- linux使用shell脚本实现自动登录scp传输文件到其他服务器