簡體   English   中英

使用聲明的encoding = utf-8 - Java從xml中刪除非UTF-8字符

[英]remove non-UTF-8 characters from xml with declared encoding=utf-8 - Java

我必須在Java中處理這種情況:

我從聲明為encoding = utf-8的客戶端獲取XML格式的請求。 不幸的是,它可能不包含utf-8字符,並且需要從我這邊的xml中刪除這些字符(遺留)。

讓我們考慮這個無效XML包含£(磅)的示例。

1)我得到xml作為帶有£的java字符串(我現在無法訪問接口,但我可能將xml作為java字符串)。 我可以使用replaceAll(£,“”)來擺脫這個角色嗎? 任何潛在的問題?

2)我得到xml作為字節數組 - 在這種情況下如何安全地處理這個操作?

1)我得到xml作為帶有£的java字符串(我現在無法訪問接口,但我可能將xml作為java字符串)。 我可以使用replaceAll(£,“”)來擺脫這個角色嗎?

我假設你想要擺脫非ASCII字符,因為你在談論一個“遺產”方面。 您可以使用以下正則表達式刪除可打印ASCII范圍之外的任何內容:

string = string.replaceAll("[^\\x20-\\x7e]", "");

2)我得到xml作為字節數組 - 在這種情況下如何安全地處理這個操作?

您需要將byte[]包裝在ByteArrayInputStream ,以便您可以使用InputStreamReader在UTF-8編碼的字符流中讀取它們,其中您指定編碼,然后使用BufferedReader逐行讀取它。

例如

BufferedReader reader = null;
try {
    reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes), "UTF-8"));
    for (String line; (line = reader.readLine()) != null;) {
        line = line.replaceAll("[^\\x20-\\x7e]", "");
        // ...
    }
    // ...

UTF-8是一種編碼; Unicode是一個字符集。 但GBP符號絕對是Unicode字符集,因此絕對可以用UTF-8表示。

如果你確實意味着UTF-8,並且你實際上試圖刪除不是UTF-8中字符的有效編碼的字節序列,那么......

CharsetDecoder utf8Decoder = Charset.forName("UTF-8").newDecoder();
utf8Decoder.onMalformedInput(CodingErrorAction.IGNORE);
utf8Decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
ByteBuffer bytes = ...;
CharBuffer parsed = utf8Decoder.decode(bytes);
...
"test text".replaceAll("[^\\u0000-\\uFFFF]", "");

此代碼從string中刪除所有4字節的utf8字符。在執行Mysql innodb varchar條目時,這可能需要用於某些目的

我從本地目錄中讀取文件時遇到了同樣的問題,並嘗試了這個:

BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF-8"));
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document xmlDom = db.parse(new InputSource(in));

您可能必須使用網絡輸入流而不是FileInputStream。

- 卡皮爾

請注意,第一步應該是您要求XML的創建者(最有可能是本地“僅打印數據”XML生成器)在發送給您之前確保其XML正確無誤。 如果他們使用Windows,最簡單的測試是要求他們在Internet Explorer中查看它,並在第一個違規字符處查看解析錯誤。

雖然他們解決了這個問題,但你可以簡單地編寫一個改變標題部分的小程序來聲明編碼是ISO-8859-1:

<?xml version="1.0" encoding="iso-8859-1" ?>

並保持其余部分不受影響。

在java機器上將字節數組轉換為String后,您將獲得(默認情況下在大多數機器上)UTF-16編碼的字符串。 擺脫非UTF-8字符的正確解決方案是使用以下代碼:

String[] values = {"\\xF0\\x9F\\x98\\x95", "\\xF0\\x9F\\x91\\x8C", "/*", "look into my eyes 〠.〠", "fkdjsf ksdjfslk", "\\xF0\\x80\\x80\\x80", "aa \\xF0\\x9F\\x98\\x95 aa"};
for (int i = 0; i < values.length; i++) {
    System.out.println(values[i].replaceAll(
                    "[\\\\x00-\\\\x7F]|" + //single-byte sequences   0xxxxxxx
                    "[\\\\xC0-\\\\xDF][\\\\x80-\\\\xBF]|" + //double-byte sequences   110xxxxx 10xxxxxx
                    "[\\\\xE0-\\\\xEF][\\\\x80-\\\\xBF]{2}|" + //triple-byte sequences   1110xxxx 10xxxxxx * 2
                    "[\\\\xF0-\\\\xF7][\\\\x80-\\\\xBF]{3}" //quadruple-byte sequence 11110xxx 10xxxxxx * 3
            , ""));
}

或者如果你想驗證某些字符串是否包含非utf8字符,你可以使用Pattern.matches:

String[] values = {"\\xF0\\x9F\\x98\\x95", "\\xF0\\x9F\\x91\\x8C", "/*", "look into my eyes 〠.〠", "fkdjsf ksdjfslk", "\\xF0\\x80\\x80\\x80", "aa \\xF0\\x9F\\x98\\x95 aa"};
for (int i = 0; i < values.length; i++) {
    System.out.println(Pattern.matches(
                    ".*(" +
                    "[\\\\x00-\\\\x7F]|" + //single-byte sequences   0xxxxxxx
                    "[\\\\xC0-\\\\xDF][\\\\x80-\\\\xBF]|" + //double-byte sequences   110xxxxx 10xxxxxx
                    "[\\\\xE0-\\\\xEF][\\\\x80-\\\\xBF]{2}|" + //triple-byte sequences   1110xxxx 10xxxxxx * 2
                    "[\\\\xF0-\\\\xF7][\\\\x80-\\\\xBF]{3}" //quadruple-byte sequence 11110xxx 10xxxxxx * 3
                    + ").*"
            , values[i]));
}

如果你有可用的字節數組,你可以更正確地過濾它們:

BufferedReader bufferedReader = null;
try {
    bufferedReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes), "UTF-8"));
    for (String currentLine; (currentLine = bufferedReader.readLine()) != null;) {
        currentLine = currentLine.replaceAll(
                        "[\\x00-\\x7F]|" + //single-byte sequences   0xxxxxxx
                        "[\\xC0-\\xDF][\\x80-\\xBF]|" + //double-byte sequences   110xxxxx 10xxxxxx
                        "[\\xE0-\\xEF][\\x80-\\xBF]{2}|" + //triple-byte sequences   1110xxxx 10xxxxxx * 2
                        "[\\xF0-\\xF7][\\x80-\\xBF]{3}" //quadruple-byte sequence 11110xxx 10xxxxxx * 3
                , ""));
    }

要使整個Web應用程序兼容UTF8,請在此處閱讀:
如何讓UTF-8在Java webapps中工作
有關字節編碼和字符串的更多信息
你可以在這里查看你的模式。
這里的 PHP也一樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM