簡體   English   中英

從Java字符串中過濾非MySQL Latin1字符

[英]Filtering non MySQL Latin1 Characters from a String in Java

我有一個使用latin1的MySQL表,不幸的是我無法更改。

在將字符串插入此表之前,我想檢查字符串是否包含不屬於latin1字符集的字符。 這樣,我可以將其從數據集中刪除。

我怎樣才能做到這一點?

例如

boolean hasNonLatin1Chars = string.chars()
                .anyMatch(c -> ...)

為了使其簡單而健壯,請利用CharsetEncoder

/** replaces any invalid character in Latin1 by the character rep */
public static String latin1(String str, char rep) {
    CharsetEncoder cs = StandardCharsets.ISO_8859_1.newEncoder()
            .onMalformedInput(CodingErrorAction.REPLACE)
            .onUnmappableCharacter(CodingErrorAction.REPLACE)
            .replaceWith(new byte[] { (byte) rep });
    try {
        ByteBuffer b = cs.encode(CharBuffer.wrap(str));
        return new String(b.array(), StandardCharsets.ISO_8859_1);
    } catch (CharacterCodingException e) {
        throw new RuntimeException(e); // should not happen
    }
}

這將用替換字符rep (當然應該是有效的Latin1字符)替換ISO_8859_1(= Latin1)中的每個無效字符集。

如果可以使用默認替換( '?' ),則可以使其更簡單:

public static String latin1(String str) {
    return new String(str.getBytes(StandardCharsets.ISO_8859_1),
          StandardCharsets.ISO_8859_1);
}

例如:

public static void main(String[] args)  {
    String x = "hi Œmar!";
    System.out.println("'" + x + "' -> '" + latin1(x,'?') + "'");
}

輸出'hi Œmar!' -> 'hi ?mar!' 'hi Œmar!' -> 'hi ?mar!'

這種方法的可能缺點是僅允許您用單個替換字符替換每個無效字符-您不能刪除它或使用多字符序列。 如果您要這樣做,並且可以合理地確定某個字符永遠不會出現在字符串中,則可以使用通常的骯臟技巧-例如,假定\永遠不會出現:

/* removes invalid Latin1 charaters - assumes the zero character never appears */
public static String latin1removeinvalid(String str) {
    return latin1(str,(char)0).replace("\u0000", "");
}

補充:如果您只想檢查有效性,那么它更簡單:

public static boolean isValidLatin1(String str) {
    return StandardCharsets.ISO_8859_1.newEncoder().canEncode(str);
}

如果您的源數據始終是UTF8,請這樣說。 然后,您將兩全其美-帶有音譯為latin1的UTF8字符將被更改; 那些沒有的將以“?”出現。

getConnection()調用中使用此命令:

?useUnicode=yes&characterEncoding=UTF-8

無需測試不良字符,無需進行代碼轉換。 MySQL自動完成所有工作。

基本拉丁語范圍0020–007F ,因此您可以檢查是否嘗試替換非拉丁字符的第一個實例與原始String匹配:

boolean hasNonLatin1Chars = string.equals((string.replaceFirst("[^\\u0020-\\u007F]", "")));

如果它包含非拉丁字符,則將返回false

有Latin-1補編( 00A0 — 00FF ),Latin Extended-A( 0100 — 017F )和Latin Extended-B( 0180 — 024F ),因此您可以根據需要修改范圍。

暫無
暫無

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

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