UTF8 数据到 std::string 或 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, '');
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, '');
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 格式将响应重新发送到客户端。

std::string中存储 utf-8 只不过是在"vector"中存储字节序列。std::string不知道任何编码内容,一旦您需要超出标准 ASCII 的工作,任何像find或像std::find这样的<algorithm>函数都不起作用。因此,如何处理这种情况取决于您,您可以尝试将输入(L"Ñ")转换为utf-8序列并尝试在std::string中找到它,或者您可以将string转换为wstring并直接处理它。恕我直言,在您的情况下,当您必须操作(搜索、提取单词、按字母拆分或替换,所有这些都超出了 ASCII 范围)输入时,您最好坚持wstring,在将其发布到客户端之前将其转换为 utf-8std::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;
}

编译并运行时的结果 版本 x64
已用时间:3065 运行时间:29

两个数量级...

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

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

  1. 找出 HTTP 服务器响应的字符编码。服务器应在标头中发送信息。
  2. 为自己获取一份指定服务器使用的编码的标准副本。
  3. 给自己一份 unicode 标准的副本。
  4. 遍历每个字形簇并根据每个规范进行转换。

第四步显然是最不平凡的一步。确切的实现取决于您要转换的编码。对于我的回答来说,这太宽泛了。

使用现有实现通常具有成本效益,这样您就不必自己执行步骤 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 簇进行比较。

第四步显然是最不平凡的一步。确切的实现取决于搜索所需的语义类型。对于我的回答来说,这太宽泛了。

使用现有实现通常具有成本效益,这样您就不必自己执行步骤 3-4。

最新更新