UTF-16、UTF-16BE、UTF-16LE编码方式的区别

UTF-16、UTF-16BE、UTF-16LE编码方式的区别

文章分类:Java编程

Java代码
  1. import  java.io.IOException;  
  2.   
  3. /**  
  4.  * UTF-16BE: 16 位 UCS 转换格式,Big Endian(最低地址存放高位字节,符合人们的阅读习惯)字节顺序   
  5.  * UTF-16LE: 16 位 UCS 转换格式,Little-endian(最高地址存放高位字节)字节顺序   
  6.  * UTF-16: 16 位 UCS 转换格式,字节顺序(是高字节在前还是低字节在前)由流中的前两字节中字节顺序标记来确定  
  7.  *   
  8.  * UTF-16BE: FE FF 字节顺序标记  
  9.  * UTF-16LE: FF FE 字节顺序标记  
  10.  */   
  11. public   class  Test {  
  12.     public   static   void  main(String[] args)  throws  IOException {  
  13.         String str = "中" ;  
  14.           
  15.         //------------编码   
  16.           
  17.         //Java里使用的是UTF-16BE方式来存储数据的   
  18.         System.out.println(Integer.toHexString(str.charAt(0 ) &  0x00FFFF  |  0xFF0000 ).substring( 2 6 )  
  19.                     .toUpperCase());//4E2D   
  20.         /*  
  21.          * 进行编码时,因为 UTF-16 编码方式本身未指定字节顺序标记,所以默认使用 Big Endian 字节  
  22.          * 顺序编码,并将 Big Endian 字节顺序标记写入到流中,所以流前面多了 FE FF 二字节的高字节  
  23.          * 顺序标记  
  24.          */   
  25.         System.out.println(byteToHex(str.getBytes("utf-16" ))); //FE FF 4E 2D    
  26.           
  27.         /*  
  28.          * 进行编码时,UTF-16BE 和 UTF-16LE charset 不会将字节顺序标记写入到流中  
  29.          * 即它们所编出的码每个字符只占二个字节,要注意的是解码时要使用同样的编码  
  30.          * 方式,不然会出现问题乱码  
  31.          */   
  32.         System.out.println(byteToHex(str.getBytes("utf-16BE" ))); //4E 2D    
  33.         System.out.println(byteToHex(str.getBytes("utf-16LE" ))); //2D 4E    
  34.           
  35.         //使用 utf-16BE 对高字节序进行解码,忽略字节顺序标记,即不会将流前二字节内容看作字节序标记   
  36.         System.out.println(new  String( new   byte []{ 0x4E , 0x2D }, "utf-16BE" )); // 中   
  37.         //使用 utf-16LE 对低字节序进行解码,忽略字节顺序标记,即不会将流前二字节内容看作字节序标记   
  38.         System.out.println(new  String( new   byte []{ 0x2D , 0x4E }, "utf-16LE" )); // 中   
  39.           
  40.         //------------解码   
  41.           
  42.         /*  
  43.          * 使用 utf-16 进行解码时,会根据流前两字节内部来确定是低还是高字节顺序,如果流的前两字节  
  44.          * 内部不是 高字节序 FE FF,也不是低字节序 FF FE时,则默认使用 高字节序 方式来解码  
  45.          */   
  46.           
  47.         //因为0x4E,0x2D为“中”字的高字节表示,所以前面需要加上 FE FF 字节顺序标记来指示它   
  48.         System.out.println(new  String( new   byte []{( byte 0xFE ,( byte 0xFF , 0x4E , 0x2D }, "utf-16" )); //中   
  49.   
  50.         //因为0x2D,0x4E为“中”字的低字节表示,所以前面需要加上 FF FE 字节顺序标记来指示它   
  51.         System.out.println(new  String( new   byte []{( byte 0xFF ,( byte 0xFE , 0x2D , 0x4E ,}, "utf-16" )); //中   
  52.           
  53.           
  54.         //使用默认 高字节顺序 方式来解码,            
  55.         System.out.println(new  String( new   byte []{ 0x4E , 0x2D }, "utf-16" )); //中   
  56.           
  57.         //因为 0x2D,0x4E 为“中”的低字节序,但 utf-16 默认却是以 高字节序来解的,所以出现乱码   
  58.         System.out.println(new  String( new   byte []{ 0x2D , 0x4E ,}, "utf-16" )); //?    
  59.     }  
  60.   
  61.     public   static  String byteToHex( byte [] bt) {  
  62.         StringBuilder sb = new  StringBuilder( 4 );  
  63.         for  ( int  b : bt) {  
  64.             sb.append(Integer.toHexString(b & 0x00FF  |  0xFF00 ).substring( 2 4 )  
  65.                     .toUpperCase());  
  66.             sb.append(" " );  
  67.         }  
  68.         return  sb.toString();  
  69.     }  
  70. }  
import java.io.IOException;

/**
 * UTF-16BE: 16 位 UCS 转换格式,Big Endian(最低地址存放高位字节,符合人们的阅读习惯)字节顺序 
 * UTF-16LE: 16 位 UCS 转换格式,Little-endian(最高地址存放高位字节)字节顺序 
 * UTF-16: 16 位 UCS 转换格式,字节顺序(是高字节在前还是低字节在前)由流中的前两字节中字节顺序标记来确定
 * 
 * UTF-16BE: FE FF 字节顺序标记
 * UTF-16LE: FF FE 字节顺序标记
 */
public class Test {
	public static void main(String[] args) throws IOException {
		String str = "中";
		
		//------------编码
		
		//Java里使用的是UTF-16BE方式来存储数据的
		System.out.println(Integer.toHexString(str.charAt(0) & 0x00FFFF | 0xFF0000).substring(2, 6)
					.toUpperCase());//4E2D
		/*
		 * 进行编码时,因为 UTF-16 编码方式本身未指定字节顺序标记,所以默认使用 Big Endian 字节
		 * 顺序编码,并将 Big Endian 字节顺序标记写入到流中,所以流前面多了 FE FF 二字节的高字节
		 * 顺序标记
		 */
		System.out.println(byteToHex(str.getBytes("utf-16")));//FE FF 4E 2D 
		
		/*
		 * 进行编码时,UTF-16BE 和 UTF-16LE charset 不会将字节顺序标记写入到流中
		 * 即它们所编出的码每个字符只占二个字节,要注意的是解码时要使用同样的编码
		 * 方式,不然会出现问题乱码
		 */
		System.out.println(byteToHex(str.getBytes("utf-16BE")));//4E 2D 
		System.out.println(byteToHex(str.getBytes("utf-16LE")));//2D 4E 
		
		//使用 utf-16BE 对高字节序进行解码,忽略字节顺序标记,即不会将流前二字节内容看作字节序标记
		System.out.println(new String(new byte[]{0x4E,0x2D},"utf-16BE"));// 中
		//使用 utf-16LE 对低字节序进行解码,忽略字节顺序标记,即不会将流前二字节内容看作字节序标记
		System.out.println(new String(new byte[]{0x2D,0x4E},"utf-16LE"));// 中
		
		//------------解码
		
		/*
		 * 使用 utf-16 进行解码时,会根据流前两字节内部来确定是低还是高字节顺序,如果流的前两字节
		 * 内部不是 高字节序 FE FF,也不是低字节序 FF FE时,则默认使用 高字节序 方式来解码
		 */
		
		//因为0x4E,0x2D为“中”字的高字节表示,所以前面需要加上 FE FF 字节顺序标记来指示它
		System.out.println(new String(new byte[]{(byte) 0xFE,(byte) 0xFF,0x4E,0x2D},"utf-16"));//中

		//因为0x2D,0x4E为“中”字的低字节表示,所以前面需要加上 FF FE 字节顺序标记来指示它
		System.out.println(new String(new byte[]{(byte) 0xFF,(byte) 0xFE,0x2D,0x4E,},"utf-16"));//中
		
		
		//使用默认 高字节顺序 方式来解码,		 	
		System.out.println(new String(new byte[]{0x4E,0x2D},"utf-16"));//中
		
		//因为 0x2D,0x4E 为“中”的低字节序,但 utf-16 默认却是以 高字节序来解的,所以出现乱码
		System.out.println(new String(new byte[]{0x2D,0x4E,},"utf-16"));//? 
	}

	public static String byteToHex(byte[] bt) {
		StringBuilder sb = new StringBuilder(4);
		for (int b : bt) {
			sb.append(Integer.toHexString(b & 0x00FF | 0xFF00).substring(2, 4)
					.toUpperCase());
			sb.append(" ");
		}
		return sb.toString();
	}
}

 

注,只有UTF-16,即只有使用Unicode编码存储或传递时,才涉及到高字节还是低字节序的问题,UTF-8一般是没有字节序的概念的,因为utf-8编码本身中就已含有了编解码转换方式了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章