UTF-16、UTF-16BE、UTF-16LE編碼方式的區別
文章分類:Java編程
- 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();
- }
- }
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編碼本身中就已含有了編解碼轉換方式了。