如果我用C ++编写一个包含一些unicode字符的随机字符串文件,我的文本编辑器告诉我,我没有创建一个有效的UTF-8文件。
// Code example
const std::string charset = "abcdefgàèíüŷÀ";
file << random_string(charset); // using std::fstream
我该怎么做才能解决这个问题?我是否需要进行大量额外的手动编码?我理解它的方式,std :: string不关心编码,只关心字节,所以当我传递一个unicode字符串并将其写入文件时,肯定该文件应包含相同的字节并被识别为UTF- 8个编码文件?
答案 0 :(得分:15)
random_string
可能是罪魁祸首;我想知道它是如何实现的。如果您的字符串确实是UTF-8编码而random_string
看起来像
std::string random_string(std::string const &charset)
{
const int N = 10;
std::string result(N);
for (int i=0; i<N; i++)
result[i] = charset[rand() % charset.size()];
return result;
}
然后它会从char
中随机charset
,在UTF-8中(正如其他海报所指出的那样)不是Unicode代码点,而是简单的字节。如果它从UTF-8多字节字符的中间选择一个随机字节作为第一个字节(或者将其放在7位ASCII兼容字符之后),那么您的输出将不是有效的UTF-8。请参阅Wikipedia和RFC 3629。
解决方案可能是transform与random_string
中的UTF-32之间的解决方案。我相信wchar_t
和std::wstring
在Linux上使用UTF-32。只要你保持在Basic Multilingual Plane范围内,UTF-16也是安全的。
答案 1 :(得分:10)
我该怎么做才能解决这个问题?我有吗 做很多额外的手册 编码?我理解它的方式, std :: string不关心 编码,只有字节,所以当我 传递一个unicode字符串并写下来 要提交,肯定该文件应该 包含相同的字节和 被识别为UTF-8编码文件?
std::string
编码不可知是正确的。它只包含一个char
元素数组。这些char
元素如何被解释为文本取决于环境。如果您的语言环境未设置为某种形式的Unicode(即UTF-8或UTF-16),那么当您输出字符串时,它将不会显示/解释为Unicode。
您确定您的字符串文字“abcdefgàèíüŷÀ”实际上是 Unicode,而不是,例如Latin-1? (ISO-8859-1或可能的Windows-1252)?您需要确定您的平台当前配置使用的区域设置。
<强> ----------- ----------- EDIT 强>
我想我知道你的问题:charset
字符串文字中的某些Unicode字符,如重音字符“À”,是双字节字符(假设为UTF- 8编码)。使用[]
函数中的random_string
运算符处理字符集字符串时,将返回Unicode字符的 half 。因此random-string
函数会创建一个无效的字符串。
例如,请考虑以下代码:
std::string s = "À";
std::cout << s.length() << std::endl;
在字符串文字被解释为UTF-8的环境中,此程序将输出2
。因此,字符串(s[0]
)的第一个字符只是Unicode字符的 half ,因此无效。由于您的random_string
函数使用[]
运算符按单个字节寻址字符串,因此您创建了无效的随机字符串。
所以是的,您需要使用std::wstring
,并使用L
前缀创建字符集字符串文字。
答案 2 :(得分:1)
在您的代码示例中,std::string charset
存储您编写的内容。也就是说,如果您使用UTF-8文本编辑器来编写它,那么您在文件输出中收到的内容就是UTF-8文本。
UTF-8只是一种编码方案,其中不同的字符使用不同的字节大小。但是,如果您使用UTF-8编辑器,它将编码,用两个字节,和表示'ñ',当您将其写入文件时,它将具有两个字节(再次是UTF- 8兼容)。
问题可能是您用于创建源C ++文件的编辑器。它可能使用latin1或其他一些编码。
答案 3 :(得分:0)