【问题标题】:Mysql truncating difficult charactersMysql截断难字符
【发布时间】:2015-08-03 11:21:23
【问题描述】:

在从站点加载一些 html 并将其保存到数据库之间的某个地方,字符被省略或更改为奇怪的东西时遇到了麻烦。流程如下:

用libcurl加载站点,这是write函数的内容:

static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
    ((std::string*)userp)->append((char*)contents, size * nmemb);
    return size * nmemb;
}

网站在 html 中设置了 utf8 作为编码类型。

字符串保留为 std::string,然后传递到 Mysql cppconn 以输入到数据库表中。

表的排序规则设置为 utf8_unicode_ci,相关字段也是如此。

但是当我在Adminer中查看表格内容时,字段中的文字已经被截断,只显示了前半部分文字,只是困难字符(é)之前的普通字符。


我注意到的一件事是,在整个程序的 cout 输出中,é 从未正确显示,而是在菱形符号中显示问号。终端设置为当前语言环境:UTF-8。

这让我想,也许我从 libcurl 得到的实际上并不是 utf-8,所以我使用 boost 库尝试将其更改为 utf-8,使用:

std::locale loc("");
std::locale conv_loc = boost::locale::util::create_info(loc, loc.name());
std::string output = boost::locale::conv::to_utf<char>(codepage_str, conv_loc);

我尝试将它放在上面粘贴的 write 函数中的 return 之前,但效果是它只是从文本中删除了有问题的字符。

我在这里俯瞰什么?


现在已经输出了有问题的名称及其 utf8 值,但对我有什么帮助?

Cuauht�moc Ruelas - 0x43 0x75 0x61 0x75 0x68 0x74 0xffffffe9 0x6d 0x6f 0x63 0x20 0x52 0x75 0x65 0x6c 0x61 0x73

【问题讨论】:

  • 字符所在字符串中的实际 (utf-8) 值是多少?它是否符合 UTF-8 定义的字符代码点?这是你应该检查的第一件事——不要使用 cout (除非你输出字符的整数值)。您应该逐个字节地检查每个字符串,以确保字符串是正确的,从源字符串开始(跟踪它并注意断开连接发生的位置)。
  • 如何检查字符所在字符串中实际的 utf-8 值是多少?
  • for (auto ch : string_value) std::cout &lt;&lt; std;:hex &lt;&lt; std::setw(2) &lt;&lt; std::showbase &lt;&lt; static_cast&lt;int&gt;(ch) &lt;&lt; " ";,例如
  • @GemmaB89 基本上,您使用错误的工具来诊断问题。您应该(如先前的评论所建议的那样)逐个倾倒字符值。如果不是这样,在您的调试器中,检查字符串不是“std::string”,而是获取指向实际缓冲区的指针并查看内存。使用诸如cout &lt;&lt; std::string 之类的“高级”例程的问题是,您可能会完全错过控制台(或调试器)可能会屏蔽的任何字符。
  • 这是有道理的,对不起,这很新,这是输出:Cuauht�moc Ruelas - 0x43 0x75 0x61 0x75 0x68 0x74 0xffffffe9 0x6d 0x6f 0x63 0x20 0x52 0x75 0x65 0x6c 0x61 07>

标签: c++ mysql boost utf-8 character-encoding


【解决方案1】:

最终自己解决了问题:

我用 libcurl 加载的网站说它是 html 字符编码元标记中的 utf8,但是一旦 libcurl 有响应字符串,错误似乎就在那里。

我决定检查网站上 html 文件的实际编码字符,并使用 Chardet python 模块进行此操作。

运行这个 python 代码:

import urllib
urlread = lambda url: urllib.urlopen(url).read()
import chardet
print chardet.detect(urlread("http://www.rottentomatoes.com/m/little_boy_2015/reviews/"))

给我:{'confidence': 0.8129867552228945, 'encoding': 'ISO-8859-2'}

字符编码检测并不完美,因此置信度不是 1,但我随后在 c++ 中使用 Boost 语言环境将字符串从 ISO-8859-2 直接转换为 UTF8,现在出现了正确的字符到处都是完美的:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-25
    • 2017-03-24
    • 2012-08-25
    • 1970-01-01
    • 1970-01-01
    • 2018-01-30
    • 2012-06-02
    相关资源
    最近更新 更多