Qt cpp - 将QString写入文本文件的干净方法

Qt cpp - Clean way to write QString into text file

本文关键字:文件 方法 文本 cpp QString Qt      更新时间:2023-10-16

我需要找到一种干净快速的方法.csv文件中编写QString。 我试过了:

QString path= QCoreApplication::applicationDirPath() + QString("/myfile.csv");
QFile file(path);
QString mystring = "Hello, world!";    
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << mystring;
file.close();
}

但它为我写了"???????"myfile.csv

由于安德烈还没有反应,我将介入并提供一些有关 OP 问题的背景信息:

来自Qt文档关于QString

QString 类提供了一个 Unicode 字符串。

QString 存储一串 16 位 QChar,其中每个 QChar 对应一个 Unicode 4.0 字符。(代码值高于 65535 的 Unicode 字符使用代理项对存储,即两个连续的 QChar。

来自Qt文档关于QTextStream::operator<<(const QString &string)

将字符串字符串写入流,并返回对 QTextStream 的引用。在将字符串写入流之前,首先使用分配的编解码器(默认编解码器为 QTextCodec::codecForLocale())对字符串进行编码。

关于一般QTextStream

在内部,QTextStream 使用基于 Unicode 的缓冲区,QTextStream 使用 QTextCodec 自动支持不同的字符集。默认情况下,QTextCodec::codecForLocale() 用于读取和写入,但您也可以通过调用 setCodec() 来设置编解码器。还支持自动 Unicode 检测。启用此功能(默认行为)后,QTextStream 将检测 UTF-16 或 UTF-32 BOM(字节顺序标记),并在读取时切换到相应的 UTF 编解码器。默认情况下,QTextStream 不会写入 BOM,但您可以通过调用 setGenerateByteOrderMark(true) 来启用它。

因此,"???????"可能Hello, World!以 UTF-16 或 UTF-32 编码,其中 OPs 视图工具(输出"???????")无法检测到这一点,甚至不支持这种编码。

安德烈·谢苗诺夫的暗示,改为:

file.write(mystring.toUtf8());

QString内容转换为 UTF-8

  • 由字节组成
  • 与 ASCII
  • 在前 127 个 ASCII 字符方面相同。

QString::toUtf8()返回QByteArray;并且QTextStream::operator<<(const QByteArray&)很可能原封不动地写入这些字节。(这在文档中甚至没有提到。

因此,Hello, World!仅包含 ASCII 表中可用的字符(代码<127)。甚至,如果OP视图工具支持/期望例如Windows 1252,它也不会注意到这一点。(我假设无法检测/处理 UTF-16 或 UTF-32 的工具可能也无法检测/处理 UTF-8。


顺便说一句,要找出"???????"实际上是什么编码,可以使用十六进制视图工具查看myfile.csv。由于输入是已知的,编码可能可以从输出中推断出来。(例如,He在 ASCIIUTF-8 中0x48 0x65,但在 UTF-16LE 中0x48 0x00 0x65 0x00,在 UTF-16BE 中0x00 0x48 0x00 0x65


我试图用MCVE重现这个问题。

testQTextStreamEncoding.cc

#include <QtWidgets>
int main(int, char**)
{
const QString qString = "Hello, World!";
const QString qPath("testQTextStreamEncoding.txt");
QFile qFile(qPath);
if (qFile.open(QIODevice::WriteOnly)) {
QTextStream out(&qFile); out << qString;
qFile.close();
}
return 0;
}

testQTextStreamEncoding.pro

SOURCES = testQTextStreamEncoding.cc
QT += widgets

cygwin上,我做到了:

$ qmake-qt5
$ make
g++ -c -fno-keep-inline-dllexport -D_GNU_SOURCE -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -isystem /usr/include/qt5 -isystem /usr/include/qt5/QtWidgets -isystem /usr/include/qt5/QtGui -isystem /usr/include/qt5/QtCore -I. -I/usr/lib/qt5/mkspecs/cygwin-g++ -o testQTextStreamEncoding.o testQTextStreamEncoding.cc
g++  -o testQTextStreamEncoding.exe testQTextStreamEncoding.o   -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread 
$ ./testQTextStreamEncoding
$ hexdump.exe -C testQTextStreamEncoding.txt
00000000  48 65 6c 6c 6f 2c 20 57  6f 72 6c 64 21           |Hello, World!|
0000000d
$

因此,我似乎无法重现OP所描述的内容。 我还尝试了在VS2013中编译和运行的代码:

$ rm testQTextStreamEncoding.txt ; ls testQTextStreamEncoding.txt
ls: cannot access 'testQTextStreamEncoding.txt': No such file or directory

(编译,在VS2013中运行)

$ hexdump.exe -C testQTextStreamEncoding.txt
00000000  48 65 6c 6c 6f 2c 20 57  6f 72 6c 64 21           |Hello, World!|
0000000d
$

同样,我无法复制。看看OP如何产生"???????"以及它实际包含的内容会很有趣。