上次介紹的是檔案的Big5轉UTF-8,但把字串轉成資料流再轉換編碼,似乎比檔案轉碼來得複雜一點:
public static String getEncodingString(String str, String srcEnc, String targetEnc) { ByteArrayInputStream bais = null; BufferedReader br = null; try { bais = new ByteArrayInputStream(str.getBytes(srcEnc)); br = new BufferedReader(new InputStreamReader(bais, srcEnc)); ByteArrayOutputStream boas = new ByteArrayOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(boas, targetEnc); osw.write(br.readLine()); osw.flush(); byte[] ba = boas.toByteArray(); for (int i=0; i<ba.length; i++) { System.out.printf("%02X ", ba[i]); } return boas.toString(targetEnc); } catch (Exception e) { e.printStackTrace(); return null; } } |
上面的method傳進的參數是要轉碼的字串、字串原編碼、要轉碼之編碼。比檔案轉碼多出的地方是:
- 在字串轉成ByteArrayInputStream時,getBytes要指定來源編碼。
- 轉碼到ByteArrayOutputStream,toString也要指定目的編碼。
以下以"一"作為測試之用,"一"在Unicode編碼是\u4E00,在Big5編碼是A440。Java字串預設編碼是Unicode,切勿String str = "一"; 這樣宣告,它必定為Unicode編碼,除非javac -encoding Big5來編譯。以下是測試用例:
byte baChOneBig5[] = new byte[2]; baChOneBig5[0] = (byte)0xA4; // Big5編碼A440 ==> 0xA4, 0x40 baChOneBig5[1] = (byte)0x40; String char1 = new String(baChOneBig5, "BIG5"); // 由byte[]轉成String就可以是Big5字串 System.out.println("Big5: " + char1); System.out.println(" >> " + getEncodingString(char1, "Big5", "Unicode")); System.out.println(" >> " + getEncodingString(char1, "Big5", "UTF-8")); |
得到的結果如下:
Big5: 一 FE FF 4E 00 >> 一 Unicode編碼\u4E00, 但不知前面的FEFF是怎麼來的。 E4 B8 80 >> 一 UTF-8在"一"的編碼。 |
其實在String char1 = new String(baChOneBig5, "BIG5");的時候,若Integer.toHexString(char1.charAt(0)).toUpperCase()會得到什麼編碼?其實不是A440,而是4E00。在存成Java String時,還是Unicode。