Как определить, содержит ли строка специальный символ, который не может быть сохранен с использованием набора символов utf8-mb4

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

Ответ 1

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

Ответ 2

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

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;
}

Ответ 3

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

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

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

  • Character.charCount
  • Character.isSupplementaryCodePoint

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

  • String.codePointAt
  • String.codePointCount