首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java中URLEncoder.encode與getBytes同為UTF-8卻輸出不同十六進制的深度解析

     編輯:程式設計綜合問答

現象重現

String a = "你好";
// getBytes輸出
a.getBytes("UTF-8"); // [-28, -67, -96, -27, -91, -67]
// URLEncoder輸出
URLEncoder.encode(a, "UTF-8"); // %E4%BD%A0%E5%A5%BD

同樣UTF-8編碼,為何字節表現截然不同?

核心差異:編碼 vs 逃逸

維度getBytes( charset )URLEncoder.encode( charset )
本質操作字符 → 字節序列(編碼)字符 → 字節序列 → %XX 形式(編碼+URL逃逸)
輸出類型byte[](原始字節)String(ASCII可打印字符)
處理非ASCII直接輸出字節值(有符號byte顯示負數)每字節轉為 %XX 十六進制大寫
處理空格編碼為 0x20轉為 + 號(application/x-www-form-urlencoded規範)
適用場景文件存儲、網絡傳輸、加密輸入URL查詢參數、表單提交、HTTP Body

字節級還原驗證

「你好」UTF-8編碼為6字節:

你 → E4 BD A0
好 → E5 A5 BD
  • getBytes:直接返回{0xE4, 0xBD, 0xA0, 0xE5, 0xA5, 0xBD},Java有符號byte顯示為負數
  • URLEncoder:將每字節格式化為%E4%BD%A0%E5%A5%BD

代碼驗證

String s = "你好";
byte[] raw = s.getBytes(StandardCharsets.UTF_8);
StringBuilder hex = new StringBuilder();
for (byte b : raw) {
    hex.append(String.format("%02X ", b & 0xFF)); // 無符號十六進制
}
System.out.println("原始字節: " + hex); // E4 BD A0 E5 A5 BD

String encoded = URLEncoder.encode(s, StandardCharsets.UTF_8.name());
System.out.println("URL編碼: " + encoded); // %E4%BD%A0%E5%A5%BD

// 反向驗證
String decoded = URLDecoder.decode(encoded, StandardCharsets.UTF_8.name());
System.out.println("解碼還原: " + decoded); // 你好

常見誤區澄清

原答案提到「UTF-8中文3字節,GB2312中文2字節」雖然正確,但未說明URLEncoder在字節基礎上又做了一層%XX轉換,這才是輸出差異的直接原因。

工程選型指南

  • 需傳輸二進制數據 → getBytes + Base64
  • 構建URL查詢字符串 → URLEncoder.encode
  • HTTP POST表單 → URLEncoder.encode(或框架自動處理)
  • 文件寫入/加密輸入 → getBytes

總結

getBytes是純編碼,URLEncoder.encode是編碼+URL逃逸。兩者服務於完全不同的協議層,不可互換。理解「字節→%XX」這一額外轉換步驟,是區分二者的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved