[英]Qt UTF-8 File to std::string Adds extra characters
我有一个UTF-8编码的文本文件,其中包含²,³,Ç和ó等字符。 当我使用以下命令读取文件时,文件似乎已正确读取(至少根据查看contents
变量内容时在Visual Studio编辑器中看到的内容)
QFile file( filePath );
if ( !file.open( QFile::ReadOnly | QFile::Text ) ) {
return;
}
QString contents;
QTextStream stream( &file );
contents.append( stream.readAll() );
file.close();
但是,一旦将内容转换为std::string
,就会添加其他字符。 例如, ²
被转换为²
,当它应该只是A²。 对于每个非ANSI字符,似乎都发生了这种情况Â
会添加额外的Â
这当然意味着在保存新文件时,输出文件中的字符不正确。
当然,我尝试过简单地执行toStdString()
,我也尝试过toUtf8
,甚至尝试过使用QTextCodec
但是每个都无法提供正确的值。
我不明白为什么从UTF-8文件转到QString,然后到std :: string会丢失UTF-8字符。 它应该能够重现最初读取的确切文件,还是我完全丢失了什么?
正如Daniel Kamil Kozar在回答中所提到的, QTextStream
不会读取编码,因此实际上并未正确读取文件。 为了正确解析字符, QTextStream
必须在读取文件之前设置其编解码器。 在下面的代码中添加了注释,以显示所需的额外文件。
QFile file( filePath );
if ( !file.open( QFile::ReadOnly | QFile::Text ) ) {
return;
}
QString contents;
QTextStream stream( &file );
stream.setCodec( QTextCodec::codecForName( "UTF-8" ) ); // This is required.
contents.append( stream.readAll() );
file.close();
您所看到的实际上是预期的行为。
字符串²
编码为UTF-8时,由字节C3 82 C2 B2
组成。 假设QTextStream
实际上可以正确识别UTF-8( 从文档中判断 ,这并不是很明显, 该文档仅在存在BOM时提及字符编码检测,而您对包含BOM的输入文件一无所知) ,我们可以假设QTextStream::readAll
返回的QString
实际上包含字符串²
。
QString::toStdString()
返回给定QString
表示的字符串的UTF-8编码变体 ,因此返回值应包含与输入文件相同的字节,即C3 82 C2 B2
。
现在,关于您在调试器中看到的内容:
0xC2 0xB2
(正确)。”。 这只是部分正确:QString在内部使用UTF-16LE,这意味着其内部字符数组包含两个16位值: 0x00C2 0x00B2
。 实际上,当每个字符编码为UTF-16时,它们映射到字符Â
和²
,这证明QString
是基于文件输入正确构建的。 但是,您的调试器似乎足够聪明,可以知道构成QString
的字节是用UTF-16编码的,因此可以正确呈现字符。 QString::toStdString
返回的std::string
的内容显示为²
假设您的调试器在没有明确说明编码的情况下使用可怕的“ ANSI代码页”将字节解析为字符,并且您使用的是英语Windows,而Windows 1252作为其默认旧版代码页,则一切都准备就绪: std::string
实际上包含字节C3 82 C2 B2
,它映射到Windows-1252中的字符²
。 无耻的自我插件:我在去年的一个会议上发表了关于字符编码的演讲 。 也许观看它可以帮助您更好地了解其中一些问题。
最后一件事: ANSI不是编码 。 根据Windows的区域设置,它可能意味着许多不同的编码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.