向資料表插入資料:英文正常,中文僅存前 7-8 字,後續截斷。部分資料庫 (如 Sybase SQL Anywhere 5.0) 不受影響。另存在無法建表 Bug。
JDBC-ODBC Bridge (Type 1 驅動) 內部 Unicode → ANSI 轉換邏輯缺陷,導致雙位元組中文字元處理錯誤。
核心思想: 將中文字串轉為「純 ASCII」字串存入,讀出後還原。利用 GB2312 編碼特性:漢字 = 兩個高位元組 (MSB=1),英文 = 單位元組 (MSB=0)。
// 寫入:中文去高位 1,英文補 0 標記
public static String toTrueAsciiStr(String str) {
StringBuffer sb = new StringBuffer();
byte[] bt = str.getBytes(); // 系統預設編碼 (GBK/Big5)
for (int i = 0; i < bt.length; i++) {
if (bt[i] < 0) { // 高位元組 (漢字一半)
sb.append((char)(bt[i] & 0x7F)); // 去掉 MSB
} else { // 英文字元
sb.append((char)0); // 標記位
sb.append((char)bt[i]); // 原字元
}
}
return sb.toString();
}
// 讀出:還原
public static String unToTrueAsciiStr(String str) {
byte[] bt = str.getBytes();
int zeroCount = 0;
for (byte b : bt) if (b == 0) zeroCount++;
byte[] bt2 = new byte[bt.length - zeroCount];
int j = 0;
for (int i = 0; i < bt.length; i++) {
if (bt[i] == 0) { // 英文標記
i++;
bt2[j++] = bt[i];
} else { // 中文高位元組
bt2[j++] = (byte)(bt[i] | 0x80); // 加回 MSB
}
}
return new String(bt2); // 系統預設編碼解碼
}
Windows 開發測試正常,部署到 Solaris 伺服器:
EncodingFilter
com.example.EncodingFilter
encoding
UTF-8
EncodingFilter
/*
public class EncodingFilter implements Filter {
private String encoding = "UTF-8";
public void init(FilterConfig cfg) {
encoding = cfg.getInitParameter("encoding");
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
req.setCharacterEncoding(encoding);
res.setCharacterEncoding(encoding);
res.setContentType("text/html;charset=" + encoding);
chain.doFilter(req, res);
}
public void destroy() {}
}
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
// MySQL
jdbc:mysql://host:3306/db?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
// Oracle (NLS_LANG 環境變數)
-Duser.language=zh -Duser.region=TW -Dfile.encoding=UTF-8
-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8
中文亂碼本質是編碼不一致。建立統一編碼規範,自動化配置到基礎設施層,才能徹底根治。