我需要找到一种干净而快速的方法来在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
答案 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-16或UTF-32中,其中OP查看工具(输出"???????"
)无法检测到此情况甚至不支持这种编码。
Andrey Semenov的提示,改为:
file.write(mystring.toUtf8());
将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
在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如何产生"???????"
以及它实际包含的内容将会很有趣。