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
,就会添加其他字符。例如,²
被转换为²
,而它应该只是 ²。这似乎发生在每个非 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
。
现在,关于您在调试器中看到的内容:
- 您在其中一条评论中指出"QString 在字符串中只有
0xC2 0xB2
(这是正确的)。QString在内部使用UTF-16LE,这意味着它的内部字符数组包含两个16位值:0x00C2 0x00B2
。事实上,当每个字符被编码为 UTF-16 时,这些映射到字符Â
和²
,这证明QString
是根据文件的输入正确构造的。但是,调试器似乎足够聪明,知道构成QString
的字节以 UTF-16 编码,从而正确呈现字符。 - 您还表示调试器将从
QString::toStdString
返回的std::string
的内容显示为²
。假设您的调试器在没有明确说明编码的情况下使用可怕的"ANSI 代码页"将字节解析为字符,并且您使用的是使用 Windows-1252 作为其默认旧代码页的英语 Windows,那么一切都适合:std::string
实际上包含字节C3 82 C2 B2
,映射到 Windows-1252 中²
字符。
无耻的自我插拔:我去年在一次会议上发表了关于字符编码的演讲。也许观看它可以帮助您更好地理解其中的一些问题。
最后一件事:ANSI不是一种编码。它可能意味着基于Windows区域设置的许多不同的编码。
- 只能向C++添加一定数量的字符
- 如何在C++中为字符串添加字符?
- 如何将字符添加到已经大小的数组中?
- 向字符串添加字符
- 如何编写模板函数来添加整数但连接字符串和字符类型?
- 在字符串中的字符前添加空格C++插入函数
- std::字符串添加到字符*
- Qt UTF-8 文件到 std::string 添加额外的字符
- 编译器将随机字符添加到我的 char 数组中
- 为什么编译器不抱怨将字符添加到 char*?
- 将作为数学运算符的字符添加到随机字符串中
- 将字符添加到 std::cin
- 如何将点字符添加到字符串中的字符
- strftime 将不需要的字符添加到我尝试显示的内容中
- 当我将字符添加到空字符串(如 " " + c)时,为什么要返回未知值?
- 如何将字符添加到 2D 数组
- 将空格字符添加到附加的每个项目,以必须擦除最后一个项目.如何改进
- "b"作为字符添加到字符串中
- 如何将字符添加到字符串中
- C++将x个字符添加到字符串数组中