UTF8 数据到 std::string 或 std::wstring
UTF8 data to std::string or std::wstring
我从 HTTP 服务器响应中收到正文字节,但我不知道如何将它们转换为 UTF8 字符串以使用它们。
我有一个想法,但我不确定它是否可行。我需要获取响应的字节并搜索它们并修改它们,所以我需要将 std::vector<BYTE>
转换为 std::wstring
或 std::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, '[=12=]');
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, '[=12=]');
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::string
或 std::wstring
中以便搜索和修改数据(带有特殊字符)并以 UTF8 重新发送响应给客户端。
在 std::string
中存储 utf-8 只不过是在 "vector" 中存储字节序列。 std::string
不知道任何编码内容,任何成员函数如 find
或 <algorithm>
函数如 std::find
将无法工作,一旦你需要超出标准 ASCII 工作。因此,如何处理这种情况取决于您,您可以尝试将输入 (L"Ñ"
) 转换为 utf-8 序列并尝试在 std::string
中找到它,或者您可以将 string
到 wstring
并直接对其进行处理。恕我直言,在您必须操作(搜索、提取单词、按字母拆分或替换,以及所有这些超出 ASCII 运行ge)的情况下,您最好坚持输入 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;
}
编译后的结果和 运行 作为版本 x64
经过时间:3065
经过时间:29
两个数量级...
I receive the body bytes from an HTTP server response and I dont know how to convert them to an UTF8 string to work with them.
您需要执行以下步骤:
- 找出 HTTP 服务器响应的字符编码。服务器应在 header.
中发送信息
- 自己获取一份指定服务器使用的编码的标准副本。
- 获取 unicode 标准的副本。
- 遍历每个字素簇并根据每个规范进行转换。
第四步显然是最不重要的一步。确切的实现取决于您要转换的编码。这对我的回答来说太宽泛了。
使用现有的实现通常是划算的,这样您就不必自己执行第 2-4 步。标准库的转换选项非常有限(仅在不同的 unicode 格式之间,以及在 native narrow 和 native wide 之间),所以你可能不能依赖它。
so I need to transform the std::vector to std::wstring
将 UTF-8 编码的字符存储在宽字符串中意义不大,因为 UTF-8 是一种窄字符编码。
But now if I want to search a character like "Ñ" in the string will work?
当然可以,但请记住,C++ 标准库的字符串算法不考虑编码,因此它可能不是实现搜索的一个选项。特别是如果您希望搜索由多个代码点组成的任意字素簇。要在 UTF-8 字符串中正确搜索任何 UTF-8 字符,您需要:
- 确定搜索比较的语义。 Ñ 应该匹配 N 吗?规范等效性如何(标准化与同一字符的 non-normalized 版本)?
- 如果您希望执行简单的、精确的字节搜索,那么标准的 C++ 功能就足够了。否则,转3.
- 获取 unicode 标准的副本。
- 遍历每个字素簇并将其与参数字素簇进行比较。
第四步显然是最不重要的一步。确切的实现取决于搜索所需的语义类型。这对我的回答来说太宽泛了。
使用现有的实现通常是划算的,这样您就不必自己执行步骤 3-4。
我从 HTTP 服务器响应中收到正文字节,但我不知道如何将它们转换为 UTF8 字符串以使用它们。
我有一个想法,但我不确定它是否可行。我需要获取响应的字节并搜索它们并修改它们,所以我需要将 std::vector<BYTE>
转换为 std::wstring
或 std::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, '[=12=]');
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, '[=12=]');
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::string
或 std::wstring
中以便搜索和修改数据(带有特殊字符)并以 UTF8 重新发送响应给客户端。
在 std::string
中存储 utf-8 只不过是在 "vector" 中存储字节序列。 std::string
不知道任何编码内容,任何成员函数如 find
或 <algorithm>
函数如 std::find
将无法工作,一旦你需要超出标准 ASCII 工作。因此,如何处理这种情况取决于您,您可以尝试将输入 (L"Ñ"
) 转换为 utf-8 序列并尝试在 std::string
中找到它,或者您可以将 string
到 wstring
并直接对其进行处理。恕我直言,在您必须操作(搜索、提取单词、按字母拆分或替换,以及所有这些超出 ASCII 运行ge)的情况下,您最好坚持输入 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;
}
编译后的结果和 运行 作为版本 x64
经过时间:3065
经过时间:29
两个数量级...
I receive the body bytes from an HTTP server response and I dont know how to convert them to an UTF8 string to work with them.
您需要执行以下步骤:
- 找出 HTTP 服务器响应的字符编码。服务器应在 header. 中发送信息
- 自己获取一份指定服务器使用的编码的标准副本。
- 获取 unicode 标准的副本。
- 遍历每个字素簇并根据每个规范进行转换。
第四步显然是最不重要的一步。确切的实现取决于您要转换的编码。这对我的回答来说太宽泛了。
使用现有的实现通常是划算的,这样您就不必自己执行第 2-4 步。标准库的转换选项非常有限(仅在不同的 unicode 格式之间,以及在 native narrow 和 native wide 之间),所以你可能不能依赖它。
so I need to transform the std::vector to std::wstring
将 UTF-8 编码的字符存储在宽字符串中意义不大,因为 UTF-8 是一种窄字符编码。
But now if I want to search a character like "Ñ" in the string will work?
当然可以,但请记住,C++ 标准库的字符串算法不考虑编码,因此它可能不是实现搜索的一个选项。特别是如果您希望搜索由多个代码点组成的任意字素簇。要在 UTF-8 字符串中正确搜索任何 UTF-8 字符,您需要:
- 确定搜索比较的语义。 Ñ 应该匹配 N 吗?规范等效性如何(标准化与同一字符的 non-normalized 版本)?
- 如果您希望执行简单的、精确的字节搜索,那么标准的 C++ 功能就足够了。否则,转3.
- 获取 unicode 标准的副本。
- 遍历每个字素簇并将其与参数字素簇进行比较。
第四步显然是最不重要的一步。确切的实现取决于搜索所需的语义类型。这对我的回答来说太宽泛了。
使用现有的实现通常是划算的,这样您就不必自己执行步骤 3-4。