StupidBeauty
Read times:1432Posted at:Sun Oct 9 21:14:10 2011
- no title specified

Qt Jambi 4.4文档翻译:QDataStream类,Class QDataStream

QDataStream类提供咯将二进制数据序列化到一个 QIODevice 中去的功能。一个数据流就是一个代表已编码信息的二进制流,它是与所运行的电脑的操作系统 、中央处理器或者字节序完全无关的。例如,使用Windows 的PC 所生成的一个数据流可以被运行Solaris 的Sun SPARC 读取。

你也可以使用一个数据流来读写未编码的二进制数据。如果你想使用一个带有“分词” ("parsing") 功能的输入流,那么就去看看 QTextStream

QDataStream类实现咯对C++的基本数据类型的序列化,例如 char short int char * 等等。对更复杂的数据的序列化是通过将数据分解成原子单位来实现的

一个数据流与 QIODevice 是紧密结合的。一个 QIODevice 表示一个输入/输出介质,你可以从中读取数据 ,也可以向其中写入数据。 QFile 类就是输入/输出设备的一个例子。

示例(向一个流中写入二进制数据):

QFile file = new QFile("file.dat");

QFile.OpenMode mode = new QFile.OpenMode();

mode.set(QFile.OpenModeFlag.WriteOnly);

file.open(mode);

QDataStream out = new QDataStream(file); //我们会将数据序列化到file中

out.writeString("the answer is"); //序列化一个字符串

out.writeInt(42); //序列化一个整数

示例(从一个流中读取二进制数据):

QFile file = new QFile("file.dat");

QFile.OpenMode mode = new QFile.OpenMode();

mode.set(QFile.OpenModeFlag.ReadOnly);

file.open(mode);

QDataStream in = new QDataStream(file); //从file中读取序列化后的数据

//提取"the answer is"和42

String str = in.readString();

int a = in.readInt();

写入到流中的每个条目都是以一个预定义的二进制格式写入的,这个格式根据条目的类型而变化。所支持的Qt 类型包括 QBrush QColor QDateTime QFont QPixmap QString(本座告诉你,QtJambi中没有QString) QVariant 和其它的很多类型。要想知道支持数据流的Qt 类型的完整列表 ,就去看 QDataStream 操作符的格式

对于整数,最好在写入之前转换成一个Qt 整数 ,并且在读取的时候以那个相同的Qt 整数的类型来读取 。这样能确保你得到你想要的大小的整数 ,并且将你与编译器和平台的差异隔离开。

举个例子吧,一个 char *字符串是勒样写入的:一个32位的整数,表示的是包括'\0'字节在内的字符串的长度 ,紧接着是包含'\0'字节在内的整个字符串的各个字符。当读取一个 char * 字符串时 ,首先读 取4字节,将它作为那个32 位的长度值 ,再读取那么多的字符 ,以构造那个 char * 字符串,其中包括'\0'终结符。

初始的输入/输出设备通常是在构造函数里设置的,但是可以使用 setDevice() 来修改。如果你到达咯数据的末尾 (或者没有设置输入/输出设备),那么 atEnd() 就会返回真。

版本设置

QDataStream的二进制格式从Qt 1.0 以来一直在变化,并且看样子会随着Qt 的变化而继续变化。当你在输入或者输出复杂的类型时,要确保是使用相同版本的流 version() )来读取和写入的。如果你同时需要前向和后向兼容性 ,那么你可以将版本号硬编码到程序中:

stream.setVersion(QDataStream.Version.Qt_4_0.value());

如果你在创建一个新的二进制数据格式,例如由你的程序所创建的文档所使用的一个文件格式,那么你可以使用QDataStream 来按照一个可移植的格式来写这些数据。典型地,你可以写入一个简短的文件头 ,其中包含一个魔数字符串和一个版本号,这样就给你自己留下咯在将来进行扩展的空间。例如:

QFile file = new QFile("file.xxx");

QFile.OpenMode mode = new QFile.OpenMode();

mode.set(QFile.OpenModeFlag.WriteOnly);

file.open(mode);

QDataStream out = new QDataStream(file);

//写入一个包含“魔数”和一个版本号的文件头

out.writeInt(0xA0B0C0D0);

out.writeInt(123);

out.setVersion(QDataStream.Version.Qt_4_0.value());

//写入数据

out.writeBytes(lots_of_interesting_data.toByteArray());

以后再像这样读取:

QFile file = new QFile("file.xxx");

QFile.OpenMode mode = new QFile.OpenMode();

mode.set(QFile.OpenModeFlag.ReadOnly);

file.open(mode);

QDataStream in = new QDataStream(file);

//读取并且检查文件头

int magic = in.readInt();

if (magic != 0xA0B0C0D0)

return XXX_BAD_FILE_FORMAT;

//读取版本号

int version = in.readInt();

if (version < 100)

return XXX_BAD_FILE_TOO_OLD;

if (version > 123)

return XXX_BAD_FILE_TOO_NEW;

if (version <= 110)

in.setVersion(QDataStream.Version.Qt_3_1.value());

else

in.setVersion(QDataStream.Version.Qt_4_0.value());

//读取数据

QByteArray lots_of_interesting_data = new QByteArray();

QByteArray data_new_in_XXX_version_1_2 = new QByteArray();

QByteArray other_interesting_data = new QByteArray();

lots_of_interesting_data.readFrom(in);

if (version >= 120)

data_new_in_XXX_version_1_2.readFrom(in);

other_interesting_data.readFrom(in);

你可以选择在序列化数据时使用什么字节序。默认的设置是大端在前 (最重要的字节 (MSB) 在前)。如果将它改变成小端在前的话会破坏可移植性 (除非读取者也变成小端在前)。我们建议保留这个设置 ,除非你有特殊的需求。

读取和写入原始的二进制数据

你可能想要从数据流/向数据流直接读取/写入你自己的原始二进制数据。可以使用readRawData()来从流中将数据读取到一个预先分配咯空间的 char * 。可以使用writeRawData()来将类似的数据写入到流中 。注意 ,任何的编码/解码工作都必须由你来做。

类似的一对函数是 readBytes() writeBytes() 。它们与对应的原始 (raw)函数有以下不同: readBytes() 首先会读取一个quint32,将它作为要读取的数据的长度,然后将那么多的数据读取到一个预先分配咯空间的 char * 中; writeBytes() 首先写入一个quint32,它表示的是数据的长度,接下来就写入数据。注意 ,对数据 (除咯那个表示长度的quint32 以外)的任何编码/解码工作要由你来做。

参见

QTextStream QVariant

Your opinions
Your name:Email:Website url:Opinion content:
- no title specified

HxLauncher: Launch Android applications by voice commands