QTextStream可以在QIODevice、QByteArray或QString上操作。使用QTextStream的流操作符,您可以方便地读写单词、行和数字。对于生成文本,QTextStream支持字段填充和对齐的格式化选项,以及数字的格式化。例如:
QFile data("output.txt");
if (data.open(QFile::WriteOnly | QFile::Truncate)) {
QTextStream out(&data);
out << "Result: " << qSetFieldWidth(10) << left << 3.14 << 2.7;
// writes "Result: 3.14 2.7 "
}
QTextStream是区域设置感知的,并且会使用正确的编解码器自动解码标准输入。例如:
QTextStream stream(stdin);
QString line;
while (stream.readLineInto(&line)) {
// ...
}
您可以通过调用seek()来寻找一个位置,当没有数据剩余可读时,atEnd()将返回true。如果你调用flush(), QTextStream将从它的写缓冲区清空所有数据到设备,并在设备上调用flush()。
默认情况下,QTextCodec::codecForLocale()用于读写,但你也可以通过调用setCodec()来设置编解码器。还支持自动Unicode检测。当此特性被启用(默认行为)时,QTextStream将检测UTF-16或UTF-32 BOM(字节顺序标记),并在读取时切换到适当的UTF编解码器。QTextStream默认不写BOM,但是你可以通过调用setGenerateByteOrderMark(true)来启用它。当QTextStream直接对QString操作时,编解码器被禁用。
有三种使用QTextStream读取文本文件的一般方法:
- 一个块一个块地,调用
readLine()
或readAll()
。 - 逐字逐句地,QTextStream支持流到qstring, QByteArrays和char*缓冲区。 单词由空格分隔,前导空格会自动跳过。
- 一个字符接一个字符,通过流进入QChar或char类型。 在解析文件时,这种方法通常用于方便的输入处理,与字符编码和行结束语义无关。 要跳过空白,调用skipWhiteSpace()。
因为文本流使用缓冲区,所以不应该使用超类的实现从流中读取。 例如,如果你有一个QFile,并直接使用QFile::readLine()而不是使用流来读取它,文本流的内部位置将与文件的位置不同步。
默认情况下,当从文本流中读取数字时,QTextStream将自动检测数字的基本表示形式。 例如,如果数字以“0x”开头,则假定为十六进制。 如果它从数字1-9开始,则假定它是十进制的,依此类推。 您可以通过调用setIntegerBase()来设置整数基数,从而禁用自动检测。 例子:
QTextStream in("0x50 0x20");
int firstNumber, secondNumber;
in >> firstNumber; // firstNumber == 80
in >> dec >> secondNumber; // secondNumber == 0
char ch;
in >> ch; // ch == 'x'
qDebug() << ch;
QTextStream支持许多格式化选项来生成文本。
- 通过调用setFieldWidth()和setPadChar()来设置字段宽度和填充字符。
- 使用setFieldAlignment()设置每个字段的对齐方式。
- 对于实数,调用setRealNumberNotation()和setRealNumberPrecision()设置生成数字的数字表示法(SmartNotation, ScientificNotation, FixedNotation)和精度。
- 通过setNumberFlags()也可以提供一些额外的数字格式化选项。
1 设置数字的输出格式
可以使用QTextStream类的setNumberFlags
方法,指定数字的输出格式,它的标志位含义介绍如下:
QTextStream::ShowBase
指定以哪一种进制进行显示,16 (“0x”), 8 (“0”), or 2 (“0b”)QTextStream::ForcePoint
如果输出类型是double或float,若这个数字不含小数部分,默认情况下不显示小数部分,若设置了该标志位,则显示小数部分QTextStream::ForceSign
在输出的数字前面加上正负号,即”+”或”-“QTextStream::UppercaseBase
在进制指示中,使用大写字母表示,如”0X”, “0B”QTextStream::UppercaseDigits
使用大写字母来表示10到35位数字,而不是小写。例如16进制中的a-f都用大写字母表示,或者科学计数法中的e使用大写E
#include <QTextStream>
int main(){
QTextStream out(stdout);
int i = 60;
out.setIntegerBase(16); // 设置16进制显示,所以使用输入输出流,也可以很容易的进行 进制转换
out << i << endl; // 3c
out.setNumberFlags(out.numberFlags() | QTextStream::ShowBase);
out << i << endl; // 0x3c
out.setNumberFlags(out.numberFlags() | QTextStream::ForceSign);
out << i << endl; // +0x3c
out.setNumberFlags(out.numberFlags() | QTextStream::UppercaseBase);
out << i << endl; // +0X3c
double d = 100;
out << d << endl; // +100
out.setNumberFlags(QTextStream::ForcePoint);
out << d << endl; // 100.000
}
2 宽度,填充和对齐方式
2.1 宽度
可以调用setFieldWidth
来设置输出流的宽度,所谓宽度是指,当在流中输出一个数时,至少产生宽度值所规定数量的字符。如果插入字符的个数小于宽度值,则用某个字符对空余的位置进行填充。
一定注意,这里的宽度是指定输出字符的最小数目,如果数目不够,则使用填充字符进行填充,而不会截断输出。如果你设置宽度为2时输出1234,仍会得到1234。
QTextStream的宽度设置与标准库的有一点不同,它不需要像标准库那样,在每一个输出符前都需要设置一次宽度。
2.2 对齐方式
对齐方式一般和宽度一起使用:
- QTextStream::AlignLeft 左对齐
- QTextStream::AlignRight 右对齐
- QTextStream::AlignCenter 居中
- QTextStream::AlignAccountingStyle 和AlignRight一样,只是数字的符号是左对齐的。
```cpp
include
int main(){ QTextStream out(stdout);
int i = 60;
out.setFieldWidth(6);
out << i << endl; // output: 60
out.setPadChar('-');
out << i << endl; // output:----60
out.setFieldAlignment(QTextStream::AlignLeft);
out << i << endl; // output:60----
out.setFieldAlignment(QTextStream::AlignRight);
out << i << endl; // output:----60
out.setFieldAlignment(QTextStream::AlignCenter);
out << i << endl; // output:--60--
out.setNumberFlags(QTextStream::ForceSign);
out.setFieldAlignment(QTextStream::AlignAccountingStyle);
out << i << endl; // output:+---60
}
<a name="eh0Ub"></a>
# 3 精度
请看下面的程序:
```cpp
#include <QTextStream>
int main(int argc, char *argv[])
{
QTextStream out(stdout);
double d = 12.3456789;
out << d << endl; // output:12.3457
Q_ASSERT(d == 12.3456789);
return 0;
}
此程序预想的输出结果应该是12.3456789,但实际的输出结果是12.3457,那么,是d的值改变了吗。当然没有,因为Q_ASSERT测试为真。
这是因为QTextStream的精度默认设置为6,而如果想要改变它的默认精度,则可以使用setRealNumberPrecision
方法。
#include <QTextStream>
int main(int argc, char *argv[])
{
QTextStream out(stdout);
out.setRealNumberPrecision(10);
double d = 12.3456789;
out << d << endl; // output:12.3456789
Q_ASSERT(d == 12.3456789);
return 0;
}