基础
-
Character set(字符集):字符的集合,带有特殊语义的符号
-
Coded character set(编码字符集):一个数值赋给一个字符的集合
-
Character-encoding scheme(字符编码方案): 编码字符集成员到八位字节(8 bit字节)的映射。编码方案定义了如何把字符编码的序列表达为字节序列。字符编码的数值不需要与编码字节相同,也不需要是一对一或一对多个的关系。原则上,把字符集编码和解码近似视为对象的序列化和反序列
-
java中:java.nio.charset包的Charset,它封装字符集抽象. 大部分的操作系统在I/O与文件存储方面仍是以字节为导向的,所以无论使用何种编码,Unicode或其他编码,在字节序列和字符集编码之间仍需要进行转化, 由java.nio.charset包组成的类满足了这个需求
-
java.nio.charset.spi包提供服务器供给接口(SPI),使编码器和解码器可以根据需要选择插入。
-
字符集名称不区分大小写(UTF-8 uft-8),也就是,当比较字符集名称时认为大写字母和小写字母相同
-
互联网名称分配机构(IANA)维护所有正式注册的字符集名称,IANA是维护字符集名称的权威登记机构
Charset
-
Charset是抽象的,通过静态工厂方法forName获取具体的实例。所有的charset方法都是线程安全的。单一的实例可以在多个线程中共享
-
可以通过isSupported()确定在JVM运行中当前指定的字符集是否可用。通过Charset SPI机制可以动态安装新的字符集。
@Test public void test(){ //返回JVM中当前有效的所有字符集 SortedMap<String, Charset> availableCharsets = Charset.availableCharsets(); Set<Entry<String, Charset>> entrySet = availableCharsets.entrySet(); Iterator<Entry<String, Charset>> iterator = entrySet.iterator(); while(iterator.hasNext()){ Entry<String, Charset> entry = iterator.next(); //规范名称 String key = entry.getKey(); Charset value = entry.getValue(); System.out.println(key+":"+value.toString()); } //判断是否支持指定的字符集 boolean supported = Charset.isSupported("UTF-8"); System.out.println("是否支持UTF-8:"+supported); Charset charset = Charset.forName("UTF-8"); boolean registered = charset.isRegistered(); System.out.println("是否在IANA注册:"+registered); }
-
字符集的比较与包含关系
@Test public void test2(){ Charset charset = Charset.forName("UTF-16"); boolean contains = charset.contains(Charset.forName("UTF-8")); System.out.println("UTF-16是否包含UTF-8:"+contains);//true charset = Charset.forName("GBK"); contains = charset.contains(Charset.forName("Big5")); System.out.println("GBK是否包含Big5:"+contains);//false 表示包含关系不存在或未知的包含关系 Charset gbk = Charset.forName("GBK"); Charset gbk2 = Charset.forName("gbk"); Charset gb2312 = Charset.forName("GB2312"); System.out.println("字符集比较:"+gbk.equals(gb2312));//false System.out.println("字符集比较:"+gbk.equals(gbk2));//true }
-
字符集编码器:如果该Charset对象能够编码字符序列,canEncode()方法返回true。如果为false,几乎所有的字符集都支持编码。主要的例外情况是带有解码器的字符集,它们可以自检测字节序列是如何编码并且之后会选择一个合适的解码方案。这些字符集通常只支持解码并且不创建自己的编码
@Test public void test3(){ Charset UTF8 = Charset.forName("UTF-8"); boolean canEncode = UTF8.canEncode(); //UTF-8是否可以编码:true System.out.println(UTF8.name()+"是否可以编码:"+canEncode); //可以使用和字符集相关的编码方案把字符序列转化为字节序列 // CharsetEncoder对象是一个状态转换引擎:字符进去,字节出来。 CharsetEncoder newEncoder = UTF8.newEncoder(); }
-
利用Charset进行ByteBuffer和CharBuffer之间的转换
-
由于计算机底层只能存储二进制字节码,因此将字符存储到节点时要对字符进行编码(字符转换成二进制字节码),而从节点取出字符显示时要进行解码(将二进制字节码转换成字符);
-
而字符集Charset则决定了该字符应该编码成怎样的二进制字节码,因此在两者之间转换时必须要确定使用的字符集;
-
由于Channel只能直接操作ByteBuffer,而处理字符时就需要在CharBuffer和ByteBuffer之间进行转换,而刚好Charset刚好提供了这样的功能;
@Test public void test4(){ Charset defaultCharset = Charset.defaultCharset(); System.out.println(defaultCharset.toString()); Charset GBK = Charset.forName("GBK"); CharBuffer cb = CharBuffer.allocate(18); cb.put("你"); cb.put("们"); cb.put("好"); //写模式切换到读模式 cb.flip(); ByteBuffer encode = GBK.encode(cb);//编码 int capacity = encode.capacity(); for(int i = 0;i<capacity;i++){ System.out.println(encode.get(i)+' '); } //你们好 System.out.println("\n"+GBK.decode(encode)); }
-