在使用 DataOutputStream.writeUTF(String) 寫入長字串時,若字串過長會拋出 UTFDataFormatException: encoded string too long。本文分析 JDK 源碼揭示根因,並給出實務規避建議。
writeUTF(String str, DataOutput out) 核心邏輯:
int strlen = str.length();
int utflen = 0;
for (int i = 0; i < strlen; i++) {
char c = str.charAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) utflen += 1; // ASCII 1 字節
else if (c > 0x07FF) utflen += 3; // BMP 輔助平面 3 字節
else utflen += 2; // 其他 BMP 字符 2 字節
}
if (utflen > 65535)
throw new UTFDataFormatException("encoded string too long: " + utflen + " bytes");
// 後續寫入邏輯:先寫 2 字節無符號短整數長度,再寫 UTF-8 字節流
關鍵點:
utflen 必須 ≤ 65,535 (2^16-1),因長度用 無符號 16 位整數 存儲。char 最大 65,535,故字符數上限約 21,845。writeUTF 不超過 20,000 字符 (約 60KB UTF-8)。OutputStreamWriter(OutputStream, "UTF-8") 直接寫入字符流,無長度限制;或序列化框架 (Protobuf、Kryo) 處理大對象。writeUTF 受限於修飾版 UTF-8 格式規範 (2 字節長度前綴),不可寫入超過 64KB UTF-8 字節流的字串。理解此限制,在網絡通訊、文件存儲等場景預先規劃分塊或選用無限制編碼方式,可避免運行時異常。