【问题标题】:How do I identify if the string contains a special character which cannot be stored using a utf8-mb4 character set如何识别字符串是否包含无法使用 utf8-mb4 字符集存储的特殊字符
【发布时间】:2012-02-05 18:23:09
【问题描述】:

如果我们正在尝试将类似的推文存储到数据库中,请参阅此tweet 和以下thread。我无法在 MySQL 中存储这条推文,我想知道如何识别字符串中是否包含 utf8-mb4 字符集无法处理的字符,以便避免存储它。

【问题讨论】:

  • 你误会了,utf8-mb4 可以存储当前支持的所有 Unicode 字符。重新阅读提到的问题。
  • mb4 对我还是不起作用,我该怎么办?
  • 您确定问题出在 MySQL 上吗?也许它与 MySQL 驱动程序或类似的驱动程序有关。
  • MySQL 说它愿意在这样的字符串中存储什么?只有 8 位 ASCII 码?在这种情况下,测试很容易。如果 MySQL 愿意存储 Unicode,你应该没有问题。如果它存储其他东西......Unicode定义了各种各样的字符类,以及一些实现相应谓词的工具(我们有一个但不容易从MySQL环境访问),因此可以决定任何字符代码如果它属于这样的 Unicode 类。
  • 您的表格的默认字符集和文本字段是否设置为 utf8mb4?

标签: java encoding utf-8 character-encoding


【解决方案1】:

给您带来问题的字符是U+1F603 SMILING FACE WITH OPEN MOUTH,它的值不能用 16 位表示。当转换为 UTF-8 时,字节值为f0 9f 98 83,它应该适合utf8mb4 字符集 MySQL 列中的问题,因此我同意其他评论者的观点,即它看起来不是 MySQL 问题。如果您可以尝试重新插入此推文,请记录 MySQL 收到的所有 SQL 语句,以确定字符在发送到 MySQL 之前或之后是否损坏。

【讨论】:

  • 我尝试以 utf8mb4 字符集将此推文存储到 MySQL 中,但它似乎失败了,我无法解决该问题,因此我想看看字符串是否包含这样的字符应用程序级别,这样我就可以避免存储此类字符串。
  • 我们知道这是您的诊断,但我们认为这是错误的;因此,如果您可以添加更多详细信息来支持或反驳您的根本原因分析,将会有所帮助。您收到错误消息吗?您可以按要求发布生成的 SQL 吗?
  • priya,如果你想简单地检查推文,方法很简单——检查推文中的任何字符是否具有大于 3 个字节的 UTF-8 表示。然而,正如@tripleee 所提到的,我们认为 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;
}

【讨论】:

  • 很抱歉,但这是一种非常随意的做法,可能会导致您的表现大打折扣。您也失去了进行字符串查找的可能性。
  • 是的,我同意你的观点,但我已经解释了做这件事的方式,如果你不同意,那没关系,但不需要 -1 的声誉。
【解决方案3】:

如果您想避免存储麻烦的字符(基本多语言平面之外的稀有花哨字符,这会给您带来问题),您可以解析 String 的字符并丢弃 String 如果它包含的代码点Character.charCount 返回2,或者Character.isSupplementaryCodePoint 返回true

按照您的要求,通过这种方式,您可以避免存储那些(由于某种原因)您的 DBMS 遇到问题的字符串。

来源:参见 javadoc

  • Character.charCount
  • Character.isSupplementaryCodePoint

而且,当你在它的时候

  • String.codePointAt
  • String.codePointCount

【讨论】:

  • for (int j = 0; j
  • 我试过上面的代码,但是没有一个计数值大于1,不确定我这样做是否正确。
  • 嗯...试试for(int j=0;j&lt;text.codePointCount();j++){boolean isBadSymbol_A=String.isSupplementaryCodePoint(text.codePointAt(j));boolean isBadSymbol_B=Character.charCount(text.codePointAt(j))&gt;1;System.out.println(isBadSymbol1_A+" "+isBadSymbol_B)}
  • 以上代码对于twitter.com/#!/Sol_Floresita17/status/162857472661524480中的推文没有返回true
  • 如何将您的推特消息导入text 字符串?可能是您在此过程中丢失了信息,例如通过一个不处理 unicode 的步骤
猜你喜欢
  • 2020-12-18
  • 2011-05-26
  • 2010-12-20
  • 2016-08-24
  • 1970-01-01
  • 2020-12-25
  • 2021-11-21
  • 1970-01-01
  • 2016-08-01
相关资源
最近更新 更多