UTF8数据到std :: string或std :: wstring

时间:2017-03-28 11:35:46

标签: c++ string encoding std wstring

我从HTTP服务器响应中收到正文字节,我不知道如何将它们转换为UTF8字符串以便与它们一起使用。

我有一个想法,但我不确定它是否有效。我需要获取响应的字节并搜索它们并修改它们,因此我需要将std::vector<BYTE>转换为std::wstringstd::string

响应的UTF8中的字节编码位于我的std::vector<BYTE>中,如何将它们转换为std::string?我应该将它们转换为std::wstring吗?

我找到了这段代码:

std::string Encoding::StringToUtf8(const std::string& str)
{
INT size = MultiByteToWideChar(CP_ACP, MB_COMPOSITE, str.c_str(), str.length(), NULL, 0);

std::wstring utf16_str(size, '\0');

MultiByteToWideChar(CP_ACP, MB_COMPOSITE, str.c_str(), str.length(), &utf16_str[0], size);

INT utf8_size = WideCharToMultiByte(CP_UTF8, 0, utf16_str.c_str(), utf16_str.length(), NULL, 0, NULL, NULL);

std::string utf8_str(utf8_size, '\0');

WideCharToMultiByte(CP_UTF8, 0, utf16_str.c_str(), utf16_str.length(), &utf8_str[0], utf8_size, NULL, NULL);

return utf8_str;

}

但是现在如果我想搜索字符串中的“Ñ”这样的字符会起作用吗?或者我要转换std::wstring中的字节并搜索“Ñ”修改std::wstring并将其转换为std::string

这两个中的哪一个是正确的?

我需要将UTF8响应放在std::stringstd::wstring中,以便搜索和修改数据(带有特殊字符),然后以UTF8重新发送对客户端的响应。

2 个答案:

答案 0 :(得分:4)

std::string中存储utf-8只不过是在“vector”中存储字节序列。 std::string无法识别任何编码内容,任何成员函数(如find<algorithm>函数如std::find一旦您需要超出标准ASCII,就无法运行。因此,由您决定如何处理这种情况,您可以尝试将输入(L"Ñ")转换为utf-8序列,并尝试在std::string中找到它,或者您可以转换string 1}}到wstring并直接在其上工作。恕我直言,在您需要操作(搜索,提取单词,按字母或替换,以及所有这些超出ASCII范围)输入时,您最好坚持wstring并在将其发布到客户端之前转换为utf- 8 std::string来自EDIT001:截至评论中提到的std::codecvt_utf8以及关于效果问题的评论。这是测试

std::wstring foo(const std::string& input)
{
    std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
    return converter.from_bytes(input.c_str());
}

std::wstring baz(const std::string& input)
{
    std::wstring retVal;
    auto targetSize = MultiByteToWideChar(CP_UTF8, 0, input.c_str(), static_cast<int>(input.size()), NULL, 0);
    retVal.resize(targetSize);
    auto res = MultiByteToWideChar(CP_UTF8, 0, input.c_str(), static_cast<int>(input.size()),
                                   const_cast<LPWSTR>(retVal.data()), targetSize);
    if(res == 0)
    {
        // handle error, throw, do something...
    }
    return retVal;
}

int main()
{
    std::string input = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut "
                        "labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco "
                        "laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in "
                        "voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat "
                        "cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";

    {
        auto start = std::chrono::high_resolution_clock::now();
        for(int i = 0; i < 100'000; ++i)
        {
            auto result = foo(input);
        }
        auto end = std::chrono::high_resolution_clock::now();
        auto res = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
        std::cout << "Elapsed time: " << res << std::endl;
    }

    {
        auto start = std::chrono::high_resolution_clock::now();
        for(int i = 0; i < 100'000; ++i)
        {
            auto result = baz(input);
        }
        auto end = std::chrono::high_resolution_clock::now();
        auto res = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
        std::cout << "Elapsed time: " << res << std::endl;
    }
    return 0;
}

编译并运行为Release x64时的结果 经历时间:3065 经历时间:29

两个数量级......

答案 1 :(得分:0)

  

我从HTTP服务器响应中收到正文字节,我不知道如何将它们转换为UTF8字符串以便与它们一起使用。

您需要按照以下步骤操作:

  1. 找出HTTP服务器响应的字符编码。服务器应该在标题中发送信息。
  2. 获取指定服务器使用的编码的标准副本。
  3. 获取unicode标准的副本。
  4. 遍历每个字形集群并根据每个规范进行转换。
  5. 第四步显然是最不重要的一步。确切的实现取决于您要转换的编码。对于我的答案来说,它太宽泛了。

    使用现有实现通常具有成本效益,因此您不必自己执行步骤2-4。标准库具有非常有限的转换选项(仅在不同的unicode格式之间,以及本机窄和本机范围之间),因此您可能不能依赖它。

      

    所以我需要将std :: vector转换为std :: wstring

    将UTF-8编码字符存储在宽字符串中是没有意义的,因为UTF-8是一种窄字符编码。

      

    但是现在如果我想在字符串中搜索像“Ñ”这样的字符会起作用吗?

    当然,尽管请记住C ++标准库的字符串算法不考虑编码,因此它可能不是实现搜索的选项。特别是如果您希望搜索由多个代码点组成的任意字形集群。要正确搜索UTF-8字符串中的任何UTF-8字符,您需要:

    1. 确定搜索比较的语义。应该Ñ匹配N?规范等价(相同字符的规范化与非规范化版本)怎么样?
    2. 如果您希望为字节搜索执行一个简单的精确字节,那么标准C ++功能就足够了。否则,请转到3.
    3. 获取unicode标准的副本。
    4. 遍历每个字形集群并将其与参数grahpeme集群进行比较。
    5. 第四步显然是最不重要的一步。确切的实现取决于搜索所需的语义类型。对于我的答案来说,它太宽泛了。

      使用现有的实现通常具有成本效益,因此您不必自己完成步骤3-4。