将ByteBuffer转换成CharBuffer的两种方式:
byteBuffer.asCharBuffer() 默认以 UTF-16BE 来编码
Charset.forName("XX").decode(byteBuffer) 转换前可指定编码方式
不同的机器可能会使用不同的字节排序方法来存储数据。“Big endian(高位优先)”将最高位的字节存入在地址最低的存储器单元。而“Little endian(低位优先)”将最高位的字节存放在地址最高的存储器单元。当存储量大于一个字节时,像int,float等,我们就要考虑字节的顺序问题了。初建的ByteBuffer默认是以Big endian的形式存储数据的,并且数据在网上传送时也常常使用Big endian形式。我们可以使用带参数的order(ByteOrder bo) 来修改字节序成ByteOrder.BIG_ENDIAN或ByteOrder.LITTLE_ENDIAN。
big endian:最高字节在地址最低位,最低字节在地址最高位,依次排列。
little endian:最低字节在最低位,最高字节在最高位,反序排列。
Big Endian
低地址 高地址
----------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 12 | 34 | 56 | 78 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Little Endian
低地址 高地址
----------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 78 | 56 | 34 | 12 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
如果我们将0x1234abcd写入到以0x0000开始的内存中,则结果为
big-endian little-endian
0x0000 0x12 0xcd
0x0001 0x34 0xab
0x0002 0xab 0x34
0x0003 0xcd 0x12
为什么要注意字节序的问题呢?你可能这么问。当然,如果你写的程序只在单机环境下面运行,并且不和别人的程序打交道,那么你完全可以忽略字节序的存在。但是,如果你的程序要跟别人的程序产生交互呢?在这里我想说说两种语言。C/C++语言编写的程序里数据存储顺序是跟编译平台所在的CPU相关的,而JAVA编写的程序则唯一采用big endian方式来存储数据
。试想,如果你用C/C++语言在x86平台下编写的程序跟别人的JAVA程序互通时会产生什么结果?就拿上面的0x12345678来说,你的程序传递给别人的一个数据,将指向0x12345678的指针传给了JAVA程序,由于JAVA采取big endian方式存储数据,很自然的它会将你的数据翻译为0x78563412。什么?竟然变成另外一个数字了?是的,就是这种后果。因此,在你的C程序传给JAVA程序之前有必要进行字节序的转换工作
。
所有网络协议也都是采用big endian的方式来传输数据的。所以有时我们也会把big endian方式称之为网络字节序
。当两台采用不同字节序的主机通信时,在发送数据之前都必须经过字节序的转换成为网络字节序后再进行传输
。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
public class BufferToText {
public static void main(String[] args) {
try {
//--以系统默认编码方式写文件
FileChannel fc = new FileOutputStream("data2.txt").getChannel();
fc.write(ByteBuffer.wrap("测试字符".getBytes()));
fc.close();
//--读文本
fc = new FileInputStream("data2.txt").getChannel();
ByteBuffer buff = ByteBuffer.allocate(1024);
fc.read(buff);
buff.flip();
//显示乱码,采用默认的编码方式(UTF-16BE)将ByteBuffer转换成CharBuffer
System.out.println(buff.asCharBuffer());
buff.rewind();//准备重读
//当前系统默认编码方式
String encoding = System.getProperty("file.encoding");
//下面我们使用系统默认的编码方式(GBK)将ByteBuffer转换成CharBuffer
System.out.println("Decoded using " + encoding + ": "
+ Charset.forName(encoding).decode(buff));//显示正常,因为写入与读出时采用相同编码方式
//--或者,先以UTF-16BE编码后再写文件
fc = new FileOutputStream("data2.txt").getChannel();
fc.write(ByteBuffer.wrap("测试字符".getBytes("UTF-16BE")));
fc.close();
// 再尝试读
fc = new FileInputStream("data2.txt").getChannel();
buff.clear();
fc.read(buff);
buff.flip();
//显示正常,可见asCharBuffer()方式是以UTF-16BE解码的
System.out.println(buff.asCharBuffer());
//--也可直接通过CharBuffer写也是可以的
fc = new FileOutputStream("data2.txt").getChannel();
buff = ByteBuffer.allocate(8);//UTF-16编码时每个字符占二字节,所以需四个
//将ByteBuffer转换成CharBuffer后再写
buff.asCharBuffer().put("测试字符");
fc.write(buff);
fc.close();
//读显示
fc = new FileInputStream("data2.txt").getChannel();
buff.clear();
fc.read(buff);
buff.flip();
//同时也采用默认的转换方式asCharBuffer将ByteBuffer转换成CharBuffer
System.out.println(buff.asCharBuffer());//显示正常
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
分享到:
相关推荐
使用nio byteBuffer 实现按行读取文件(大文件) 在window/linux/macOS上均测试通过 对于中文乱码也已处理成功 完整注释,可随需求更改 有问题请邮件:mly610865580@126.com
仿安卓ByteBuffer 完美组包、拆包
Android
主要解决从流中获取数据,缓存,拆解,可用于TCP粘包问题
【IT十八掌徐培成】Java基础第26天-05.ByteBuffer-mark-pos-limit-cap-flip.zip
在NIO中,数据的读写操作始终是与缓冲区相关联的(读取时信道(SocketChannel)将数据读入缓冲区,写入时首先要将发送的数据按顺序填入缓冲区) 缓冲区是定长的,基本上它只是一个列表,它的所有元素都是基本数据类型。...
易语言汇编版ByteBuffer源码。主要用于各种网络协议的组包 具体用法可以点上面的网址 功能和jAVA的一样。@10371178。Tags:易语言汇编版ByteBuffer源码。
java实现使用javolution完成数据接收过程中大小端转换的问题
protobuf+long+bytebuffer,利用protobuf.js实现编解码 所需的三个js库
ios-byteBuffer [![CI状态]( Lee / ios-byteBuffer.svg?style = flat)]( Lee / ios-byteBuffer ) 用法 #分配 ByteBuffer *buffer = [ByteBuffer initWithOrder: ByteOrderLittleEndian]; #输入数据 - ( ...
java api之ByteBuffer基础、应用场景、实战讲解 文档中有丰富的例子代码实现
易语言汇编版ByteBuffer源码主要用于各种网络协议的组包 具体用法可以点上面的网址 功能和jAVA的一样
java api之ByteBuffer基础、应用场景、实战讲解
java snmp 源码 Java NIO java nio 简介 Java NIO(New IO)是用于Java(来自Java ...如:ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer 、DoubleBuffer 等。 Buffer的基本使用 通过allo
dena-bytebuffer
在公司做项目的时候发现用Netty进行TCP/IP通信的Netty客户端接收到的数据进制乱码,经过摸索,终于成功解决了这个鸡肋的问题
jdk api-ServerSocketChannel、Selector、ByteBuffer结合实现网络报文间的通讯
NULL 博文链接:https://zheng12tian.iteye.com/blog/1094811