我的應用程式正在從端點接收資料。我對接收到的資料進行一些處理并將其插入資料庫。
在某些時候我遇到了編碼問題,因為接收到的資料是 UTF-8 并且我的資料庫使用 LATIN1。顯示的錯誤是:
[org.hibernate.util.JDBCExceptionReporter] 錯誤:編碼“UTF8”中位元組序列為 0x2020 的字符在編碼“LATIN1”中沒有等效項
在大多數情況下,我可以通過像這樣替換它來解決它:
String text = org.apache.commons.lang.StringUtils.replace(s, "\u2020", " ");
但現在錯誤是:
錯誤 [org.hibernate.util.JDBCExceptionReporter] 錯誤:編碼“UTF8”中位元組序列為 0xe2 0x9c 0xa8 的字符在編碼“LATIN1”中沒有等效項
我怎樣才能替換這個十六進制?PS:不幸的是,更改資料庫編碼不是一種選擇。這是一個遺留系統。
uj5u.com熱心網友回復:
UTF-8 0xe29ca8是閃閃發光。與您已經處理的方式等效UTF-8 0x2020,您可以手動將其替換為類似于三個火花的任何 Latin1 字符(組合)。但是,沒有規范的方法可以做到這一點。本質上,您必須檢查上面的所有字符0xFF。
這里有點奇怪的是你的代碼似乎可以處理Strings,嚴格來說,JavaStrings總是 UTF-16。但是,UTF-8 是 UTF-16 的子集,因此可以安全地假設 JavaString可以表示 UTF-8 字符序列。
在您描述的場景中,您通常會接收位元組資料并使用 aCharsetDecoder將 UTF-8 位元組資料轉換為字串,并使用 aCharsetEncoder將字串轉換為 Latin1 位元組資料。onUnmappableCharacter()如果字符或位元組序列在各自的編碼中沒有表示,則這兩個類都具有指定要執行的操作的方法。接收輸入 asString消除了控制輸入位元組編碼的可能性,并且轉發輸出 asString消除了控制輸出位元組編碼的可能性。
在這種特定情況下,從字串到 Latin1 位元組字串的轉換可能是由資料庫驅動程式或資料庫本身完成的,似乎無法控制。您可以通過將字串轉換為 Latin1 位元組字串、處理所有不可映射的字符然后將其轉換回字串以將其傳遞給資料庫驅動程式來解決此問題。
uj5u.com熱心網友回復:
感謝您的回答,他們幫助了我。我意識到我必須分別處理每種編碼。我將用我制作的代碼來補充答案。
- 我做了重音替換(到 pt-br);
- 我用空格替換了特定的編碼;
正如 Izruo 所說,我需要使用 UTF-16 編碼。在我給出的示例中(0xE2 0x9C 0xA8),我應用了替換“\u2728”。在“手掌”表情符號(編碼為 0xF0 0x9F 0xA4 0xA6)中,我應用了兩個替換:“\uD83E”和“\uDD26”。
public static void main(String[] args) throws Exception {
String rawString = "Teste com acentua??es";
byte[] bytes = rawString.getBytes(StandardCharsets.UTF_8);
String utf8EncodedString = new String(bytes, StandardCharsets.UTF_8);
System.out.println(convertToLatin1(utf8EncodedString));
}
public static String convertToLatin1(String utf8String) throws Exception {
if (utf8String == null || utf8String.trim().length() == 0) {
return UtilString.EMPTY;
}
String newString = replaceAccents(utf8String);
newString = StringUtils.replace(newString, "\u2728", " ");
newString = StringUtils.replace(newString, "\u277C", " ");
newString = StringUtils.replace(newString, "\u277D", " ");
newString = StringUtils.replace(newString, "\u277E", " ");
newString = StringUtils.replace(newString, "\u277F", " ");
newString = StringUtils.replace(newString, "\u2665", " ");
newString = StringUtils.replace(newString, "\u2705", " ");
newString = StringUtils.replace(newString, "\ud83d", " ");
newString = StringUtils.replace(newString, "\ude4b", " ");
newString = StringUtils.replace(newString, "\ud83c", " ");
newString = StringUtils.replace(newString, "\udffb", " ");
newString = StringUtils.replace(newString, "\u2340", " ");
newString = StringUtils.replace(newString, "\u200d", " ");
newString = StringUtils.replace(newString, "\u2640", " ");
newString = StringUtils.replace(newString, "\ufe0f", " ");
newString = StringUtils.replace(newString, "\uD83E", " ");
newString = StringUtils.replace(newString, "\uDD70", " ");
newString = StringUtils.replace(newString, "\uDD20", " ");
newString = StringUtils.replace(newString, "\uDD26", " ");
return newString;
}
private static final String PLAIN_ASCII = "AaEeIiOoUu" //
"ááééííóóúúYy" //
"?aêê??????Yy" //
"??EeIi??UuYy" //
"????????üüYy" //
"Aa" //
"??" //
"Nn" //
;
private static final String UNICODE = "\u00C0\u00E0\u00C8\u00E8\u00CC\u00EC\u00D2\u00F2\u00D9\u00F9" //
"\u00C1\u00E1\u00C9\u00E9\u00CD\u00ED\u00D3\u00F3\u00DA\u00FA\u00DD\u00FD" //
"\u00C2\u00E2\u00CA\u00EA\u00CE\u00EE\u00D4\u00F4\u00DB\u00FB\u0176\u0177" //
"\u00C2\u00E2\u00CA\u00EA\u00CE\u00EE\u00D4\u00F4\u00DB\u00FB\u0176\u0177" //
"\u00C4\u00E4\u00CB\u00EB\u00CF\u00EF\u00D6\u00F6\u00DC\u00FC\u0178\u00FF" //
"\u00C5\u00E5" //
"\u00C7\u00E7" //
"\u00D1\u00F1";
public static String replaceAccents(String aString) {
StringBuilder stringbuilder = new StringBuilder();
for (int i = 0; i < aString.length(); i ) {
char c = aString.charAt(i);
int position = UNICODE.indexOf(c);
if (position > -1) {
stringbuilder.append(PLAIN_ASCII.charAt(position));
} else {
stringbuilder.append(c);
}
}
return stringbuilder.toString();
}
因此,如果您遇到類似的問題,請獲取 UTF-16 編碼(我在 compart.com 上找到了它,但 fileformat.info 沒問題)并應用您想要的替換。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/468104.html
上一篇:字串的實際用途是什么?
下一篇:字符陣列到字串并復制字符\0
