| 編碼方式 | 格式範例 | 適用場景 |
| Unicode Escape | \u4e2d\u6587 | Java 原始碼、Properties 檔、JSON 序列化 |
| UTF-8 Hex | E4 B8 AD E6 96 87 | URL 編碼、二進位協定、除錯檢視位元組 |
完整工具類實作
import java.nio.charset.StandardCharsets;
import java.text.Normalizer;
public final class ChineseEncoder {
private ChineseEncoder() {} // 工具類禁止實例化
/**
* 字串轉 Unicode Escape (\uXXXX)
* @param input 原始字串
* @return 轉換後字串,非 BMP 字元會產生雙代理對
*/
public static String toUnicodeEscape(String input) {
if (input == null) return null;
StringBuilder sb = new StringBuilder(input.length() * 6);
for (char c : input.toCharArray()) {
if (c <= 0x7F && c != '\\') { // ASCII 可列印字元保持原樣 (可依需求調整)
sb.append(c);
} else {
sb.append(String.format("\\u%04x", (int) c));
}
}
return sb.toString();
}
/**
* Unicode Escape 還原字串
* @param escaped 含 \uXXXX 格式字串
* @return 還原後字串
*/
public static String fromUnicodeEscape(String escaped) {
if (escaped == null) return null;
StringBuilder sb = new StringBuilder();
int i = 0;
while (i < escaped.length()) {
if (escaped.charAt(i) == '\\' && i + 1 < escaped.length() && escaped.charAt(i + 1) == 'u') {
if (i + 5 < escaped.length()) {
try {
int code = Integer.parseInt(escaped.substring(i + 2, i + 6), 16);
sb.append((char) code);
i += 6;
continue;
} catch (NumberFormatException ignored) {}
}
}
sb.append(escaped.charAt(i++));
}
return sb.toString();
}
/**
* 字串轉 UTF-8 十六進制 (大寫,空格分隔)
* @param input 原始字串
* @return 如 "E4 B8 AD E6 96 87"
*/
public static String toUtf8Hex(String input) {
if (input == null) return null;
byte[] bytes = input.getBytes(StandardCharsets.UTF_8);
StringBuilder sb = new StringBuilder(bytes.length * 3);
for (int i = 0; i < bytes.length; i++) {
if (i > 0) sb.append(' ');
sb.append(String.format("%02X", bytes[i] & 0xFF));
}
return sb.toString();
}
/**
* UTF-8 Hex 還原字串
* @param hex 如 "E4 B8 AD" 或 "E4B8AD"
* @return 還原字串
*/
public static String fromUtf8Hex(String hex) {
if (hex == null) return null;
String clean = hex.replaceAll("\\s+", "");
if (clean.length() % 2 != 0) throw new IllegalArgumentException("Hex 長度需為偶數");
byte[] bytes = new byte[clean.length() / 2];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) Integer.parseInt(clean.substring(i * 2, i * 2 + 2), 16);
}
return new String(bytes, StandardCharsets.UTF_8);
}
/**
* 字串轉 URL 編碼 (application/x-www-form-urlencoded)
*/
public static String toUrlEncoded(String input) {
try {
return java.net.URLEncoder.encode(input, StandardCharsets.UTF_8.name());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
String test = "中文測試123";
System.out.println("原文: " + test);
System.out.println("Unicode Escape: " + toUnicodeEscape(test));
System.out.println("UTF-8 Hex: " + toUtf8Hex(test));
System.out.println("URL Encoded: " + toUrlEncoded(test));
System.out.println("--- 還原測試 ---");
System.out.println(fromUnicodeEscape(toUnicodeEscape(test)));
System.out.println(fromUtf8Hex(toUtf8Hex(test)));
}
}
執行結果
原文: 中文測試123
Unicode Escape: \u4e2d\u6587\u6e2c\u8a66123
UTF-8 Hex: E4 B8 AD E6 96 87 E6 B8 AC E8 A9 A6 31 32 33
URL Encoded: %E4%B8%AD%E6%96%87%E6%B8%AC%E8%A9%A6123
--- 還原測試 ---
中文測試123
中文測試123
補充:處理 Emoji 與補充平面字元
Java char 為 UTF-16 代碼單元,補充平面字元 (如 Emoji 😀 U+1F600) 會佔用兩個 char (Surrogate Pair)。上方 toUnicodeEscape 會輸出 \ud83d\ude00。若需輸出單一 \U0001F600 格式,需使用 codePointAt 遍歷:
public static String toUnicodeEscapeFull(String input) {
if (input == null) return null;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < input.length(); ) {
int cp = input.codePointAt(i);
if (cp <= 0x7F && cp != '\\') {
sb.append((char) cp);
} else if (cp <= 0xFFFF) {
sb.append(String.format("\\u%04x", cp));
} else {
sb.append(String.format("\\U%08x", cp));
}
i += Character.charCount(cp);
}
return sb.toString();
}
效能建議
- 大量轉換時預估長度初始化
StringBuilder 容量。
- 避免在迴圈中建立大量臨時物件 (如
String.format),可手動拼接十六進制字元。
- 使用
StandardCharsets.UTF_8 避免編碼查找開銷。
- 上一篇文章: JavaEE Servlet 重導向:response.sendRedirect 完整解析
- 下一篇文章: Java Web Session 逾時設定完整指南:web.xml、註解與程式碼三種方式
Copyright ©
程式碼之家 All Rights Reserved