Qt/c++程序有一个函数,它将一个对象的数据(_token
)写入一个文件,如下所示:
QFile f( _tokenFile);
if (!f.open( QIODevice::WriteOnly)) {
qDebug() << "Unable to open token file for writing" << f.errorString();
return false;
}
QByteArray tokenBa;
QDataStream ds( &tokenBa, QIODevice::WriteOnly);
ds << _token;
tokenBa = qCompress( tokenBa);
f.write( tokenBa);
f.close();
_token是以下struct
的实例:
struct Token {
QString accessToken;
QString refreshToken;
QString clientSecret;
QString authCode;
QTime expiryTime;
enum AuthState {
A_Invalid,
A_RequestAuth,
A_Authenticated,
};
AuthState state;
Token() : state( A_Invalid) {}
bool isValid() const {
if (accessToken.isEmpty() ||
refreshToken.isEmpty()) {
return false;
}
return true;
}
void inValidate() {
accessToken.clear();
refreshToken.clear();
clientSecret.clear();
authCode.clear();
expiryTime = QTime();
}
void cleanUp() {
accessToken.clear();
refreshToken.clear();
clientSecret.clear();
authCode.clear();
expiryTime = QTime();
}
};
当文件被保存时,它在开始时有4个额外的字节,这使文件呈现为无效的zlib文件。
0000000 0000 5e01 9c78 904d 4f5d 5082 871c fa9f
0000020 353e 25cd 6975 2c2f d563 4c2c 62b8 cad1
我们可以看到上面的字节5-6是9C 78
,这是zlib签名,但在这之前的4个字节是问题。
检查压缩数据是否正确,执行以下操作:
dd if=file.token bs=1 skip=4 | openssl zlib -d
这就产生了预期的结果(用于测试)。
问题在于应用程序将此数据读取回数据对象:
QFile f( _tokenFile);
if (!f.exists()) {
qDebug() << "Token file doesn't exist" << f.fileName();
return false;
}
if (!f.open( QIODevice::ReadOnly)) {
qDebug() << "Unable to open token file for reading" << f.errorString();
return false;
}
QByteArray tokenBa = f.readAll();
f.close();
if (tokenBa.isEmpty()) {
qDebug() << "Token file is empty.";
return false;
}
tokenBa = qUncompress( tokenBa);
QDataStream ds( &tokenBa, QIODevice::ReadOnly);
ds >> _token;
返回null -因为前面有4个多余的字节。我可以放一些代码来跳过这4个字节,但我怎么知道它总是4个字节呢?相反,我想确定文件数据都是zlib压缩的。
我的问题是如何避免这些字节被保存在第一个地方,以便在重新读取格式是已知的zlib类型?
您无法避免它们,因为稍后的qUncompress需要它们:
注意:如果你想使用这个函数来解压缩使用zlib压缩的外部数据,你首先需要在包含数据的字节数组前加上一个4字节的头。报头必须包含未压缩数据的预期长度(以字节为单位),以无符号、大端序、32位整数表示。