Qt cpp - 将 QString 写入文本文件的简洁方法

Qt cpp - Clean way to write QString into text file

我需要找到一种干净快速的方法来在 .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

中为我写 "???????"

由于 Andrey 尚未做出反应,我将介入并提供一些有关 OP 问题的背景信息:

来自 Qt 文档。关于 QString:

The QString class provides a Unicode character string.

QString stores a string of 16-bit QChars, where each QChar corresponds one Unicode 4.0 character. (Unicode characters with code values above 65535 are stored using surrogate pairs, i.e., two consecutive QChars.)

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

Writes the string string to the stream, and returns a reference to the QTextStream. The string is first encoded using the assigned codec (the default codec is QTextCodec::codecForLocale()) before it is written to the stream.

一般来说QTextStream

Internally, QTextStream uses a Unicode based buffer, and QTextCodec is used by QTextStream to automatically support different character sets. By default, QTextCodec::codecForLocale() is used for reading and writing, but you can also set the codec by calling setCodec(). Automatic Unicode detection is also supported. When this feature is enabled (the default behavior), QTextStream will detect the UTF-16 or the UTF-32 BOM (Byte Order Mark) and switch to the appropriate UTF codec when reading. QTextStream does not write a BOM by default, but you can enable this by calling setGenerateByteOrderMark(true).

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

Andrey Semenov的提示,改为:

file.write(mystring.toUtf8());

QString 内容转换为 UTF-8 其中

  • 由字节组成
  • 等同于ASCII concerning the first 127 ASCII个字符。

QString::toUtf8() returns QByteArray; and QTextStream::operator<<(const QByteArray&) 很可能会原封不动地写入这些字节。 (文档中甚至没有提到这一点。)

因此,Hello, World! 仅包含 ASCII table 中可用的字符(代码 < 127)。即使,如果 OPs 查看工具 supports/expects 例如Windows 1252 它不会注意到这一点。 (我假设不能 detect/process UTF-16 或 UTF-32 的工具可能也不能 detect/process UTF-8。)


顺便说一句。要找出编码 "???????" 实际上是什么,可以使用 hex-view 工具查看 myfile.csv。由于输入是已知的,因此可以从输出中推断出编码。 (例如,He 在 ASCII UTF-8 中是 0x48 0x65,但在 UTF-16LE 中是 0x48 0x00 0x65 0x00,在 UTF- 中是 0x00 0x48 0x00 0x65 16BE.)


我尝试用 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 如何生成 "???????" 以及它实际包含的内容会很有趣。