将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();
}
}
}
分享到:
相关推荐
当我们在编写或读取Java源代码(.java文件)时,如果不正确地设置或识别文件的编码方式,就可能导致乱码的出现。例如,一个使用GBK编码的Java文件在UTF-8环境下打开,由于解码方式不匹配,原本的中文字符就会显示为...
5. **效率优化**:如果这是一个高性能的工具,那么可能采用了缓冲区(`ByteBuffer`, `CharBuffer`)来提高转换效率。 6. **实用函数**:可能定义了一些静态方法,方便在项目中便捷地进行编码转换。 在实际开发中,...
在Java Web开发中,UTF-8转ASCII的场景通常出现在需要与只支持ASCII编码的系统或服务交互时。由于ASCII编码的局限性,它无法直接识别和处理UTF-8编码中的非英文字符,因此需要进行转换。 实现UTF-8转ASCII的方法有...
GBK是中国大陆广泛使用的汉字编码标准,而UTF-8是Unicode的一种变长编码方式,支持全球多种语言,包括汉字,且在互联网上被普遍采用。 GBK全称为“Great Wall Code”或“GBK General Standard”,它是GB2312的扩展...
// 使用Unicode编码器将CharBuffer编码为UTF-8字节数组 ByteBuffer unicodeBytes = unicodeEncoder.encode(charBuffer); // 将UTF-8字节数组转换回字符串 return new String(unicodeBytes.array(), "UTF-8"); ...
4. **编码与解码**:NIO提供了编码和解码工具,如Charset类用于字符编码转换,而ByteBuffer和CharBuffer之间的转换则可以通过CharsetEncoder和CharsetDecoder实现。 5. **文件系统操作**:NIO提供FileChannel,可以...
理解并熟练掌握GB18030编码的处理方式对于开发涉及中文字符的应用尤其关键,可以避免因编码不兼容导致的数据丢失或显示异常问题。 总之,GB18030编码是一种广泛应用于中国地区的字符编码标准,尤其是在处理大量汉字...
然而,在处理不同来源的数据时,如读取或写入文件,就需要明确指定正确的编码方式,避免乱码问题。 1. **System.getProperty("file.encoding")**:Java系统属性中,"file.encoding"代表默认的文件编码,但需要注意...
UTF-8是一种变长的Unicode编码方式,它可以表示Unicode字符集中所有的字符,且在ASCII范围内与ASCII编码一致,这样既支持英文,也能处理中文和其他语言。 在Java中,进行GBK到UTF-8的转换主要涉及到`java.nio....
Buffer 中有多种类型,例如 ByteBuffer、CharBuffer、DoubleBuffer 等,每种类型都对应一个 primitive type 数据。ByteBuffer 是其中最重要的一个子类,因为在 java.io.channels 中定义的各种 channel 的 IO 操作...
Java NIO(New Input/Output)API是在JDK 1.4版本中引入的一个重要的改进,它是对传统Java IO API的补充,旨在提供更高效、更灵活的数据输入和输出方式,特别是对于高并发和高性能的应用场景,如服务器端程序。...
在Java编程语言中,将字符串转换为16进制ASCII值是一个常见的操作,尤其是在处理数据...3. 处理Unicode字符时,需要考虑字符集和编码方式。 理解这些概念和方法,对于在Java开发过程中处理字符串编码问题至关重要。
Java编程语言在处理字符编码时,常常涉及到不同的字符集,如GBK(GB2312的扩展)和UTF-8。这些字符集是用于表示文本数据的不同方式,特别是在中文环境下显得尤为重要。`java gb2312_utf8`这个主题涉及的是如何在Java...
在Java NIO中,有如ByteBuffer、CharBuffer、IntBuffer等类型,它们都继承自抽象类Buffer。缓冲区允许我们预先读写大量数据,减少了对系统调用的依赖。 2. **通道(Channel)**:通道是数据的来源或去向,例如...
缓冲区有多种类型,如ByteBuffer、CharBuffer、IntBuffer等,它们都是抽象类Buffer的子类。缓冲区具有容量、位置、限制和标记等属性,这些属性使得对数据的操作更加可控和高效。 在【第3节】 Java NIO流-缓冲区操作...
Java提供了多种类型的缓冲区,如ByteBuffer、CharBuffer、IntBuffer等,它们都是抽象类Buffer的子类。缓冲区有固定大小,并且可以标记当前位置,方便读写操作。 3. **选择器(Selector)**:选择器允许单个线程检查...
Java提供了多种类型的缓冲区,如ByteBuffer、CharBuffer、IntBuffer等,分别对应不同数据类型。缓冲区具有固定大小,可以进行读写操作,并有特定的方法如put、get用于数据存取。 3. **选择器(Selectors)**:选择...
Java NIO中有多个缓冲区类,如ByteBuffer、CharBuffer、IntBuffer等,分别对应不同数据类型。 3. **选择器(Selectors)**:选择器是NIO的一个关键特性,它允许单线程同时监控多个通道,从而实现多路复用。当通道上...
在处理字符集时,Java NIO提供了`Charset`类,它代表了一种字符编码方式。`CharsetDecoder`是`Charset`的子类,用于将字节解码为字符。当我们从文件或网络读取数据时,通常不知道数据使用的是哪种字符集,这时就需要...
此外,`ByteBuffer`还可以通过`CharsetEncoder`和`CharsetDecoder`处理字符串的编码和解码。 5. **FileChannel和SocketChannel的应用**:`FileChannel`用于文件I/O操作,它允许直接从文件读取数据或将数据直接写入...