![](/img/trans.png)
[英]remove non-UTF-8 characters from xml with declared encoding=utf-8 - Java
[英]Remove characters not-suitable for UTF-8 encoding from String
我在網站上有一個文本區域,用戶可以在其中編寫任何內容。 當用戶復制粘貼一些文本或包含非 UTF 8 字符的內容並將它們提交到服務器時會發生問題。
Java 成功地處理了它,因為它支持 UTF-16,但我的 mySql 表支持 UTF-8,因此插入失敗。
我試圖在業務邏輯本身中實現某種方式,以刪除任何不適合 UTF-8 編碼的字符。
目前我正在使用此代碼:
new String(java.nio.charset.Charset.forName("UTF-8").encode(myString).array());
但它用其他一些晦澀的字符替換了不適合 UTF-8 的字符。 這對最終用戶來說也不好看。 有人可以介紹一下使用 Java 代碼解決這個問題的任何可能的解決方案嗎?
編輯:例如,插入此類值時出現異常
java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x8A\x0D\x0A...' for column
java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x80\xF0\x9F...' for column
UTF-8 不是字符集,它是一種字符編碼,就像 UTF-16 一樣。
UTF-8 能夠將任何 unicode 字符和任何 unicode 文本編碼為字節序列,因此沒有不適合 UTF-8 的字符。
您正在使用String
的構造函數,它只接受一個字節數組( String(byte[] bytes) ),根據 javadocs :
通過使用平台的默認 charset解碼指定的字節數組來構造一個新的 String 。
它使用平台的默認字符集來解釋字節(將字節轉換為字符)。 不要使用這個。 相反,在將字節數組轉換為String
,請使用String(byte[] bytes, Charset charset)構造函數指定您希望顯式使用的編碼。
如果您對某些字符有問題,這很可能是由於在服務器端和客戶端(瀏覽器 + HTML)使用了不同的字符集或編碼。 確保在任何地方都使用 UTF-8,不要混合編碼,也不要使用平台的默認編碼。
一些閱讀如何實現這一目標:
也許這個問題的CharsetDecoder的答案有幫助。 您可以將CodingErrorAction更改為 REPLACE 並在我的示例“?”中設置替換。 這將為無效字節序列輸出給定的替換字符串。 在此示例中,讀取並解碼了UTF-8 解碼器功能和壓力測試文件:
CharsetDecoder utf8Decoder = Charset.forName("UTF-8").newDecoder();
utf8Decoder.onMalformedInput(CodingErrorAction.REPLACE);
utf8Decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
utf8Decoder.replaceWith("?");
// Read stress file
Path path = Paths.get("<path>/UTF-8-test.txt");
byte[] data = Files.readAllBytes(path);
ByteBuffer input = ByteBuffer.wrap(data);
// UTF-8 decoding
CharBuffer output = utf8Decoder.decode(input);
// Char buffer to string
String outputString = output.toString();
System.out.println(outputString);
您的代碼中的問題是您在byte[]
上調用new String
。 encode
的結果是一個 ByteBuffer,一個 ByteBuffer 上的array
的結果是一個byte[]
。 構造函數new String(byte[])
將使用您計算機的平台默認編碼; 它在您運行的每台計算機上都可能不同,因此這不是您想要的。 您至少應該將字符集作為第二個參數傳遞給 String 構造函數,盡管我不確定您會想到哪個字符集。
我不確定您為什么要這樣做:如果您的數據庫使用 UTF-8,它將為您進行編碼。 您只需要將未編碼的字符串傳遞給它。
UTF-8 和 UTF-16 都可以編碼整個 Unicode 6 字符集; 沒有可以由 UTF-16 編碼但不能由 UTF-8 編碼的字符。 因此,不幸的是,您問題的那部分無法回答。
對於一些背景:
我認為這可能對您有用從字符串中刪除 UTF-8 重音的簡單方法?
嘗試使用 Normalizer 作為,
s = Normalizer.normalize(s, Normalizer.Form.NFD);
當 MySQL 列使用舊的utf8
編碼時,每個字符僅使用 3 個字節並且該值包含一個 4 字節字符時,您將遇到此問題。
實際的解決方案是在 MySQL 中使用utf8mb4
而不是utf8
。
否則,這是我刪除所有 4 字節字符的骯臟解決方法:
public String removeUtf8Mb4(String text) {
StringBuilder result = new StringBuilder();
StringTokenizer st = new StringTokenizer(text, text, true);
while (st.hasMoreTokens()) {
String current = st.nextToken();
if(current.getBytes().length <= 3){
result.append(current);
}
}
return result.toString();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.