Фильтрация не-MySQL Latin1 символов из строки в Java - PullRequest
0 голосов
/ 21 сентября 2018

У меня есть таблица MySQL, в которой используется латиница 1, к сожалению, я не могу это изменить.

Прежде чем вставлять строки в эту таблицу, я хотел бы проверить, содержит ли строка символ, не входящий в набор символов латиницы 1,Таким образом, я могу удалить его из своего набора данных.

Как я могу это сделать?

например

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

Ответы [ 3 ]

0 голосов
/ 21 сентября 2018

Чтобы сделать его простым и надежным, используйте 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
    }
}

. Это заменит каждый недопустимый набор символов в ISO_8859_1 (= Latin1) заменяющим символом rep (что, конечно,, должен быть действительным символом 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,'?') + "'");
}

output '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);
}
0 голосов
/ 30 сентября 2018

Если ваши исходные данные соответствуют UTF8, то так и скажите.Тогда вы получите лучшее из обоих миров - символы UTF8, которые имеют транслитерацию на латиницу 1, будут изменены;те, которые не будут отображаться как '?'.

Используйте это в вызове getConnection():

?useUnicode=yes&characterEncoding=UTF-8

Нет проверки на плохие символы, нет преобразования в вашем коде.MySQL выполняет всю работу автоматически.

0 голосов
/ 21 сентября 2018

Диапазон Basic Latin * равен 0020–007F, поэтому вы можете проверить, соответствует ли попытка замены первого экземпляра нелатинского символа оригиналу String:

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

Это вернет false, если содержит нелатинский символ.

Существует Дополнение Latin-1 (00A0 — 00FF), Расширенное латинское-A (0100 — 017F) и Расширенное латинское-B (0180 — 024F), чтобы при необходимости вы могли изменить диапазон.

...