You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native还原QT zlib compress2压缩文件时头部校验错误求助

问题描述

在QT环境中通过zlib的compress2()函数生成的二进制压缩文件,在React Native应用中使用react-zlib-js库的inflate()方法解压时,出现「Error: incorrect header check」错误。尝试过inflateSync、inflateRaw等方法,也尝试移除文件前4字节,但问题依旧。不过在Node.js环境中使用node:zlib可以正常解压该文件,需要解决React Native端的解压问题。


QT压缩代码

QByteArray qCompress(const uchar* data, int nbytes, int compressionLevel)
{
    if (nbytes == 0) {
        return QByteArray(4, '\0');
    }
    if (!data) {
        qWarning("qCompress: Data is null");
        return QByteArray();
    }
    if (compressionLevel < -1 || compressionLevel > 9)
        compressionLevel = -1;
    ulong len = nbytes + nbytes / 100 + 13;
    QByteArray bazip;
    int res;
    do {
        bazip.resize(len + 4);
        res = ::compress2((uchar*)bazip.data()+4, &len, data, nbytes, compressionLevel);
        switch (res) {
        case Z_OK:
            bazip.resize(len + 4);
            bazip[0] = (nbytes & 0xff000000) >> 24;
            bazip[1] = (nbytes & 0x00ff0000) >> 16;
            bazip[2] = (nbytes & 0x0000ff00) >> 8;
            bazip[3] = (nbytes & 0x000000ff);
            break;
        case Z_MEM_ERROR:
            qWarning("qCompress: Z_MEM_ERROR: Not enough memory");
            bazip.resize(0);
            break;
        case Z_BUF_ERROR:
            len *= 2;
            break;
        }
    } while (res == Z_BUF_ERROR);
    return bazip;
}

React Native原解压代码

const zlib = require("react-zlib-js");
import { writeFile, readFile } from "react-native-fs";

async function decompressBinaryDatabaseFile() {
    try {
      const buffer = await readFile(fullBinaryFileName, "base64");

      await zlib.inflate(buffer, { raw: true }, (err: any, result: string) => {
        if (err) {
          console.log("Error decompressing database file: ", err);
        } else {
          console.log("Decompressed database file: ", result);
          writeFile(fullDatabaseFileName, result, "base64")
            .then((success) => {
              console.log("FILE WRITTEN!");
              openDatabase();
            })
            .catch((err) => {
              console.log(err.message);
            });
        }
      });
    } catch (error) {
      console.log("Error decompressing database file: ", error);
    }
  }

Node.js正常解压代码

const zlib = require('node:zlib');
const fs = require('node:fs');
const file = "./4826dd1c8821d8e08030a80ed0c12ef9";

var data = fs.readFileSync(file, "hex");

data = data.slice(4);

zlib.inflate(data, function(err, buffer) {
    if (err) throw err;

    fs.writeFileSync("output.db", buffer);
      
});

解决方法

问题根源

  1. QT的compress2()生成的是原始deflate格式的压缩数据(无zlib标准头部和校验尾部),同时在数据前添加了4字节的原始数据长度标识。
  2. React Native端原代码的问题:直接传递base64字符串给zlib方法,未转成二进制数组;移除前4字节的操作未作用在正确的二进制数据上;未明确指定原始deflate模式的参数。

修改后的React Native解压代码

const zlib = require("react-zlib-js");
import { writeFile, readFile } from "react-native-fs";

// base64转Uint8Array
function base64ToUint8Array(base64) {
  const binaryString = atob(base64);
  const bytes = new Uint8Array(binaryString.length);
  for (let i = 0; i < binaryString.length; i++) {
    bytes[i] = binaryString.charCodeAt(i);
  }
  return bytes;
}

// Uint8Array转base64
function uint8ArrayToBase64(bytes) {
  const binaryString = String.fromCharCode(...bytes);
  return btoa(binaryString);
}

async function decompressBinaryDatabaseFile() {
  try {
    const base64Buffer = await readFile(fullBinaryFileName, "base64");
    // 将base64转为二进制数组
    const fullData = base64ToUint8Array(base64Buffer);
    // 移除前4字节的原始长度标识
    const compressedData = fullData.slice(4);

    // 使用inflateRaw处理原始deflate格式数据
    zlib.inflateRaw(compressedData, (err, result) => {
      if (err) {
        console.log("Error decompressing database file: ", err);
        return;
      }
      // 将解压后的二进制数据转为base64写入文件
      const outputBase64 = uint8ArrayToBase64(result);
      writeFile(fullDatabaseFileName, outputBase64, "base64")
        .then(() => {
          console.log("FILE WRITTEN!");
          openDatabase();
        })
        .catch((err) => {
          console.log(err.message);
        });
    });
  } catch (error) {
    console.log("Error decompressing database file: ", error);
  }
}

关键修改点

  • 新增base64与Uint8Array的互转函数,确保zlib处理的是二进制数组而非字符串
  • 正确移除压缩数据前4字节的原始长度标识
  • 使用inflateRaw()方法(或inflate()配合{raw: true}参数)处理原始deflate格式的压缩数据

内容的提问来源于stack exchange,提问作者Jeevo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 08:03:11