Ale*_*Ale 4 c++ qstring qt iostream
我需要找到一个干净,快捷的方式写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();
}
Run Code Online (Sandbox Code Playgroud)
但它经常为我"???????"在myfile.csv
由于 Andrey 尚未做出反应,我将介入并提供有关 OP 问题的一些背景信息:
来自 Qt 文档。关于QString:
该即QString类提供了一个Unicode字符串。
QString存储 16 位QChar的字符串,其中每个QChar对应一个 Unicode 4.0 字符。(代码值大于 65535 的 Unicode 字符使用代理对存储,即两个连续的QChar。)
来自 Qt 文档。关于QTextStream::operator<<(const QString &string):
将字符串string写入流,并返回对QTextStream的引用。在将字符串写入流之前,首先使用指定的编解码器(默认编解码器为QTextCodec::codecForLocale())对字符串进行编码。
大约QTextStream在一般:
在内部,QTextStream使用基于 Unicode 的缓冲区,而QTextCodec由 QTextStream 使用以自动支持不同的字符集。默认情况下,QTextCodec::codecForLocale()用于读写,但您也可以通过调用setCodec()设置编解码器。还支持自动 Unicode 检测。启用此功能时(默认行为),QTextStream将检测 UTF-16 或 UTF-32 BOM(字节顺序标记)并在读取时切换到适当的 UTF 编解码器。QTextStream默认不写入 BOM,但您可以通过调用setGenerateByteOrderMark (true)启用此功能。
因此,"???????"可能Hello, World!以UTF-16或UTF-32编码,其中 OP 视图工具(输出"???????")无法检测到这种情况,甚至不支持这种编码。
Andrey Semenov的提示,改为:
file.write(mystring.toUtf8());
Run Code Online (Sandbox Code Playgroud)
所述转换QString内容以UTF-8 ,其
QString::toUtf8()返回QByteArray;并且QTextStream::operator<<(const QByteArray&)很可能将这些字节写入不变。(这甚至没有在文档中提到。)
因此,Hello, World!仅由 ASCII 表中可用的字符组成(代码 < 127)。即使 OP 视图工具支持/期望Windows 1252,它也不会注意到这一点。(我假设无法检测/处理 UTF-16 或 UTF-32 的工具也可能无法检测/处理 UTF-8。)
顺便提一句。要找出"???????"实际编码是什么,myfile.csv可以使用十六进制视图工具查看。由于输入是已知的,编码可能可以从输出中推导出来。(例如,He是0x48 0x65在ASCII和UTF-8,但0x48 0x00 0x65 0x00在UTF-16LE和0x00 0x48 0x00 0x65在UTF-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;
}
Run Code Online (Sandbox Code Playgroud)
和testQTextStreamEncoding.pro:
file.write(mystring.toUtf8());
Run Code Online (Sandbox Code Playgroud)
在cygwin 上,我做了:
#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;
}
Run Code Online (Sandbox Code Playgroud)
因此,似乎我无法在我身边重现 OP 所描述的内容。我也用在VS2013编译运行的代码试了一下:
SOURCES = testQTextStreamEncoding.cc
QT += widgets
Run Code Online (Sandbox Code Playgroud)
(编译,在VS2013中运行)
$ 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
$
Run Code Online (Sandbox Code Playgroud)
再次,我无法复制。看看 OP 如何产生"???????"以及它实际包含的内容会很有趣。