因爲MySQL 5.1不支持4字節的UTF-8序列,我需要替換/刪除這些字符串中的4字節序列。如何在Java中使用UTF-8字符串替換/刪除4(+)字節的字符?
我正在尋找一種乾淨的方式來替換這些字符。
Apache庫正在用一個問號替換字符,這種情況很好,儘管當然ASCII等效將更好。
N.B.輸入來自外部來源(電子郵件名稱),此時升級數據庫並不是解決方案。
因爲MySQL 5.1不支持4字節的UTF-8序列,我需要替換/刪除這些字符串中的4字節序列。如何在Java中使用UTF-8字符串替換/刪除4(+)字節的字符?
我正在尋找一種乾淨的方式來替換這些字符。
Apache庫正在用一個問號替換字符,這種情況很好,儘管當然ASCII等效將更好。
N.B.輸入來自外部來源(電子郵件名稱),此時升級數據庫並不是解決方案。
我們最終在Java中爲這個問題實現了以下方法。 Basicaly用更高的代碼點替換字符,然後替換最後3字節的UTF-8字符。
偏移量計算是爲了確保我們保持在unicode代碼點上。
public static final String LAST_3_BYTE_UTF_CHAR = "\uFFFF";
public static final String REPLACEMENT_CHAR = "\uFFFD";
public static String toValid3ByteUTF8String(String s) {
final int length = s.length();
StringBuilder b = new StringBuilder(length);
for (int offset = 0; offset < length;) {
final int codepoint = s.codePointAt(offset);
// do something with the codepoint
if (codepoint > CharUtils.LAST_3_BYTE_UTF_CHAR.codePointAt(0)) {
b.append(CharUtils.REPLACEMENT_CHAR);
} else {
if (Character.isValidCodePoint(codepoint)) {
b.appendCodePoint(codepoint);
} else {
b.append(CharUtils.REPLACEMENT_CHAR);
}
}
offset += Character.charCount(codepoint);
}
return b.toString();
}
謝謝。我用這個來避免轉換我的整個MySQL字符集。我的數據中不需要外星人角色或便便角色。 – Robert 2017-01-04 00:26:42
5字節utf-8序列以111110xx-字節開頭,6字節utf-8序列以1111110x-字節開頭。需要注意的是,沒有1-4字節的utf-8序列的後續字節包含較大的字節,因爲後續字節始終爲10xxxxxx格式。
因此,你可以通過字節,每次你看到一個字節的類型111110xx然後只發出'?'到輸出流/數組,同時跳過輸入中的下4個字節;模擬6字節序列。
無論如何,5字節和6字節的序列在UTF-8中無效 - 這並不是說它們不能出現在源文本中。 – 2012-02-13 12:59:18
最好是安全的 – 2012-02-13 13:07:24
如果5字節和6字節的序列不合法,它們(應該)不會成爲問題。我的問題是目前有4byte序列是合法的,但mysql支持mysql。 – pvgoddijn 2012-02-14 12:06:15
另一個簡單的解決方案是使用正則表達式[^\u0000-\uFFFF]
。例如在java中:
text.replaceAll("[^\\u0000-\\uFFFF]", "\uFFFD");
謝謝,優秀的答案 – tjeubaoit 2017-01-23 07:02:10
你是在開玩笑。 MySQL在這個時代仍然不支持Unicode?這是不合情理的。當你只能處理1,2或3字節的UTF-8序列時,假裝你支持Unicode,這與說你在僅支持1字節的ASCII序列時支持Unicode一樣重要。要麼您支持任何合法的Unicode代碼點,要麼您不支持Unicode。這是一個二元的東西。聽起來像MySQL不支持Unicode。請告訴我這是一個笑話。 – tchrist 2012-02-15 22:03:27
@tchrist:MySQL 5.5.3及更高版本通過新的「utf8mb4」「字符集」(http://dev.mysql.com/doc/refman/5.5/en/charset-unicode.html)支持正確的UTF-8。 。但是,「utf8」「字符集」僅支持最多3個字節的UTF-8多字節字符,據報道可防止不同MySQL版本之間的複製問題。在未來的MySQL版本中,「utf8」可能會變成「utf8mb4」的別名。 – ninjalj 2012-02-18 09:26:57
類似於[這個問題](http://stackoverflow.com/questions/8491431/remove-4-byte-characters-from-a-utf-8-string)除了它要求在PHP而不是Java的解決方案。 – 2016-08-05 15:27:51