Как определить, содержит ли строка специальный символ, который нельзя сохранить с помощью набора символов utf8-mb4 - PullRequest
10 голосов
/ 09 января 2012

Обратитесь к этому твиту и следующему потоку , где мы пытаемся сохранить подобный твит в базе данных.Я не могу сохранить этот твит в MySQL, я хотел бы знать, как определить, содержит ли строка символ, который не может быть обработан набором символов utf8-mb4, чтобы я мог избежать его сохранения.

Ответы [ 3 ]

4 голосов
/ 11 января 2012

Символ, который представляет для вас проблему, - U+1F603 SMILING FACE WITH OPEN MOUTH, значение которого не может быть представлено в 16 битах.При преобразовании в UTF-8 значения байтов f0 9f 98 83, которые должны без проблем помещаться в столбце MySQL с набором символов utf8mb4, поэтому я согласен с другими комментариями, что это не проблема MySQL.Если вы можете попытаться повторно вставить этот твит, зарегистрируйте все операторы SQL, полученные MySQL, чтобы определить, не повреждены ли символы до или после отправки их в MySQL.

1 голос
/ 17 января 2012

Вместо того, чтобы найти специальный символ строки, вы можете сделать одну вещь, которую вы можете конвертировать строку в шестнадцатеричный формат, а затем обратно вы можете преобразовать это в предыдущую строку

public static synchronized String toHex(byte [] buf){
    StringBuffer strbuf = new StringBuffer(buf.length * 2);
    int i;
    for (i = 0; i < buf.length; i++) {
        if (((int) buf[i] & 0xff) < 0x10){
            strbuf.append("0");
        }
        strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
    }
    return strbuf.toString();
}

Используя функцию ниже, выможно преобразовать обратно в исходную строку

public synchronized static byte[] hexToBytes(String hexString) {
    HexBinaryAdapter adapter = new HexBinaryAdapter();
    byte[] bytes = adapter.unmarshal(hexString);
    return bytes;
}
0 голосов
/ 18 января 2012

Если вы хотите избежать хранения проблемных символов (редких необычных символов за пределами базовой многоязычной плоскости, которые вызывают проблемы), вы можете проанализировать символы String и отбросить String, если он содержит кодовые точки, для которыхCharacter.charCount возвращает 2, или для которого Character.isSupplementaryCodePoint возвращает true.

Таким образом, как вы просили, вы можете избежать хранения тех строк, с которыми (по некоторым причинам) у вашей СУБД есть проблемы.

Источники: см. Javadoc для

  • Character.charCount
  • Character.isSupplementaryCodePoint

и, пока вы на нем

  • String.codePointAt
  • String.codePointCount
...