从Java字符串中过滤非MySQL Latin1字符

时间:2018-09-21 12:17:58

标签: java mysql utf-8 iso-8859-1

我有一个使用latin1的MySQL表,很遗憾,我无法更改它。

在将字符串插入此表之前,我想检查字符串是否包含不属于latin1字符集的字符。这样我可以将其从数据集中删除。

我该怎么做?

例如

<li *ngIf="data.delivery_status==='3' || data.delivery_status==='6'">
    <td><span class="btn btn-success btn-sm">Sentt - success</span></td>
</li>
<li *ngIf="!(data.delivery_status==='3' || data.delivery_status==='6')">
    <td><span class="btn btn-danger btn-sm">Sent - danger</span></td>
</li>

3 个答案:

答案 0 :(得分:0)

要使其简单而稳定,请利用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!'

此方法的可能缺点是仅允许您用单个替换字符替换每个无效字符-您不能删除它或使用多字符序列。 如果您要这样做,并且可以合理地确定某个字符永远不会出现在您的字符串中,则可以使用通常的肮脏技巧-例如,假设\u0000永远不会出现:

/* 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);
}

答案 1 :(得分:0)

如果您的源数据始终为UTF8,请这样说。然后,您将两全其美-带有音译为latin1的UTF8字符将被更改;那些没有的将以'?'出现。

getConnection()呼叫中使用它:

?useUnicode=yes&characterEncoding=UTF-8

无需测试不良字符,无需进行代码转换。 MySQL自动完成所有工作。

答案 2 :(得分:-1)

Basic Latin range0020–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),因此您可以根据需要修改范围。 / p>