繁体   English   中英

Qt UTF-8文件到std :: string添加额外的字符

[英]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

现在,关于您在调试器中看到的内容:

  1. 您已经在注释之一中指出“ QString的字符串中只有0xC2 0xB2 (正确)。”。 这只是部分正确:QString在内部使用UTF-16LE,这意味着其内部字符数组包含两个16位值: 0x00C2 0x00B2 实际上,当每个字符编码为UTF-16时,它们映射到字符² ,这证明QString是基于文件输入正确构建的。 但是,您的调试器似乎足够聪明,可以知道构成QString的字节是用UTF-16编码的,因此可以正确呈现字符。
  2. 您还声明了调试器将从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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM