QT学习-输入与输出
概要:
QT通过QIODevice这个封装能够读写字节块“设备”的提取器来实现输入输出,其子类如下:
QFile |
在本地文件系统和嵌入式资源中存取文件 |
QTemporaryFile |
创建或访问本地文件系统中的临时文件 |
QBuffer |
从一个QByteArrary中读数据或将数据写入到一个QByteArray中 |
QProcess |
运行外部程序并处理进程间的通信 |
QTcpSocket |
使用TCP协议传输数据流 |
QUdpSocket |
通过网络发送或接收UDP数据流 |
QSslSocket |
利用SSL/TLS在网络上传输加密的数据流 |
其中,QProcess,QTcpSocket,QUdpSocket,QSslSocket是顺序存储设备,只能顺序访问,而QFile,QTemporaryFile, QBuffer是随机访问文件,可随机访问,可使用QIODevice::seek()来重定位文件指针。
另外,Qt也提供了两个更高级的流类,可用于向任何QIODevice设备中读或写数据。其中QDataStream用于读写二进制数据,而QTextStream用于读写文本数据。
读写二进制文件:
方法:1、实例化QFile对象打开文件
2、建立QDataStream流对象并与文件关联
3、设置流对象版本
4、使用该流对象插入/提取数据
示例1(在一个名为facts.dat的文件中储存一个整形数据、一个QImage以及一个QMap<QString,QColor>)
1 QImage image("philip.png"); 2 3 QMap<QString,QColor> map; 4 5 map.insert("red",Qt::red); 6 map.insert("green",Qt::green); 7 8 QFile file("facts.dat") 9 if(!file.open(QIODevice::WriteOnly)) 10 { 11 std::cerr<<"Cannot open the file" 12 <<qPrintable(file.errorString()) 13 <<std::endl; 14 return; 15 } 16 17 QDataStream out(&file); 18 out.setVersion(QDataStream::Qt_4_3); 19 20 out<< quint32(0x12345678)<<image<<map;
1、实例化QFile对象打开文件(8行)
2、建立QDataStream流对象并与文件关联(17行)
3、设置流对象版本(18行)
4、使用该流对象插入/提取数据(20行)
其中的qPrintable()宏伟QString返回一个const char*对象,因为我们使用cerr流对象输出,所以转换时必须的。
版本号是一个整数,会影响Qt的数据类型(QByteArray,QFont,QImage,QPixMap,QString,QVariant等)表示方式,我们使用的是Qt_4_3的版本号,即整数9。
然后使用quint32强制写入无符号的32位整数,使用这个整数表示当前的文件格式,例如 Java 的 class 文件的魔术数字就是 0xCAFEBABE。
当QFile变量离开作用域后就会被自动关闭,如果想要重用流对象out,就得手动关闭QFile对象。
示例2:(在上述创建的文件中读取数据)
1 quint32 n; 2 QImage image; 3 QMap<QString, QColor> map; 4 5 QFile file("facts.dat"); 6 if (!file.open(QIODevice::ReadOnly)) { 7 std::cerr << "Cannot open file for reading: " 8 << qPrintable(file.errorString()) << std::endl; 9 return; 10 } 11 12 QDataStream in(&file); 13 in.setVersion(QDataStream::Qt_4_3); 14 15 in >> n >> image >> map;
1、实例化QFile对象打开文件(5行)
2、建立QDataStream流对象并与文件关联(12行)
3、设置流对象版本(13行)
4、使用该流对象插入/提取数据(15行)
用于读取数据的QDataStream版本和用于写入的版本一样,以保证数据的正常读取。
错误处理:
流对象有一个status()值,分别为QDataStream::OK,QDataStream::ReadPastEnd,QDataStream::ReadCorruptData。如果错误发生,则>>操作符总是读取0值或空值。
自定义类型的读写:
若想使用QDataStream处理自定义数据类型,可以对<<和>>进行运算符重载
QDataStream &operator<<(QDateStream &out, const Class&class); QDataStream &operator>>(QDateStream &in, Class&class);
语法规则和C++一样,在此不再赘述。
为自定义类型重载流操作符可以方便的俄输出和写入自定义类型的容器类。例如我们定义了Painting这个类类型,并创建了一个QList<Painting>对象,则写入它:
QList<Painting> paintings; out << painting;
读取它:
QList<Painting> paintings; in >> paintings;
如果想一次性读写有一个文件,可以直接使用QIODevice的write()和readAll()函数。
bool copyFile(const QString &source, const QString & dest) { QFile sourceFile.open(source); if(!sourceFile.open(QIODevice::ReadOnly)) return false; QFile destFile.open(dest); if(!destFile.open(QIODevice::WriteOnly)) return false; destFile.write(sourceFile.readAll()); return sourceFile.error() == QFile::NoError && destFile.error() == QFile::NoError; }
读写文本文件:
QT提供QTextStream类读写纯文本文件以及如HTML、XML和源代码等其他格式的文本文件。QTextStream使用16位的QChar基本数据单元,考虑了Unicode编码与本地编码转换的问题,并处理了由于操作系统的不同而导致行尾符不同的问题(Windows \r\n UNIX|Max OS X \n)。
写入数据:
用QTextStream对象写入数据与QDataStream对象基本一致。
QFile file("sf-book.txt"); if(!file.open(QIODevice::WriteOnly) { std::cerr<<"Cannot open file for writing" <<qPrintable(file.errorString())<<std::endl; return; } QTextStream out(&file); out<< "Thomas"<<"M. Disch: "<<344<<endl;
实际上被写入的是“ThomasM. Disch: ”这样运用一下代码就不能读会“Thomas” “M. Disch: ”
那么使用QDataStream为什么不会发生这种问题呢,因为它在字符串前面保存了每个字符串的长度
读取文件:
1、通过在Qchar上使用>>一个字符一个字符的读取
2、使用QTextStream::readLine()读取整行
3、使用QTextStream::readAll()读取整个文件
格式控制:
与C++相仿,QT提供了大批流操作器和成员函数用以控制格式输出,其中成员函数如下:
setIntergerBase(int) | |
0 | 前缀自动检测 |
2 | 二进制 |
8 | 八进制 |
10 | 十进制 |
16 | 十六进制 |
setNumberFlags() | |
ShowBase | 前缀显示(0b/0/0x) |
ForceSign | 实数中总是显示符号 |
ForcePoint | 数字中总是显示十进制分隔符 |
UppercaseBase | 前缀大写 |
UppercaseDigits | 十六进制中大写字母 |
setFiledAlignment(FieldAlignment) | |
AlignLeft | 左对齐 |
AlignRight | 右对齐 |
AlignCenter | 居中对齐 |
AlignAccountingStyle | 在符号和数字之间填充 |
setPadChar(QChar) | 设置填充字符 |
SetRealNumberPrecision(int) | |
FixedNotation Fixed | 定点计数法 |
ScientificNotation | 科学计数法 |
SmartNotation | 自动 |
setRealNumberPrecision(int) | |
设置数字的最大位数(默认6) |
setFieldWidth(int) |
设置字段的最小尺寸(默认0) |
setPadChar(QChar) |
设置填充字符(默认为空格) |
注意这些流对象方法的首字母是小写的,而它们的参数(枚举值)首字母大写。
2013-05-12 by QZ1012
参考文献《C++ GUI Programming with Qt4》