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

时间:2018-03-26 09:07:42

标签: c++ qt iostream qstring

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

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

1 个答案:

答案 0 :(得分:4)

由于安德烈尚未作出反应,我将介入并提供有关OP问题的背景知识:

来自Qt doc。关于QString

  

QString类提供Unicode字符串。

     

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

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

  

将字符串 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-16UTF-32中,其中OP查看工具(输出"???????")无法检测到此情况甚至不支持这种编码。

Andrey Semenov的提示,改为:

file.write(mystring.toUtf8());

QString内容转换为UTF-8

  • 由字节
  • 组成
  • 与前ASCII个字符的ASCII相同。

QString::toUtf8()返回QByteArray;并且QTextStream::operator<<(const QByteArray&)很可能不会改变这些字节。 (这甚至没有在文档中提到过。)

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

顺便说一下。要找出实际上是"???????"的编码,可以使用十六进制视图工具查看myfile.csv。由于输入是已知的,因此可以从输出中推断出编码。 (例如He在ASCII UTF-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如何产生"???????"以及它实际包含的内容将会很有趣。