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 类型?