21xrx.com
2025-03-21 17:13:12 Friday
文章检索 我的文章 写文章
C++:解压读取资源文件
2023-06-27 11:32:49 深夜i     8     0
C++ 解压 读取 资源文件

在很多应用程序中,为了避免程序过大,在程序中会使用一些资源文件,例如图片、音频、字体等。这些资源文件都被打包成了二进制文件,存储在程序中。但是,如果直接从程序中读取这些资源文件,会浪费程序的内存空间。因此,一种比较好的方式是将这些资源文件压缩成一个二进制文件,程序需要用到某个资源文件时再解压读取。

在C++中,可以使用Zlib库来进行压缩和解压缩。下面是一个简单的例子,用来解压读取压缩后的资源文件:

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include "zlib.h"
using namespace std;
// 定义压缩前后数据的结构体
struct DataBlock {
 uint32_t size; // 压缩前数据大小
 uint32_t csize; // 压缩后数据大小
 uint8_t *data; // 压缩前数据
};
// 读取资源文件
vector<DataBlock> readResourceFile(string filename) {
 vector<DataBlock> res;
 ifstream f(filename, ios::binary);
 if (!f)
  cout << "Can't open resource file " << filename << endl;
  return res;
 
 // 逐个读取资源文件中的数据块
 while (!f.eof()) {
  DataBlock b;
  f.read((char *)&b.size, sizeof(uint32_t));
  f.read((char *)&b.csize, sizeof(uint32_t));
  b.data = new uint8_t[b.csize];
  f.read((char *)b.data, b.csize);
  res.push_back(b);
 }
 f.close();
 return res;
}
int main(int argc, char *argv[]) {
 // 读取资源文件 into data vector
 vector<DataBlock> data = readResourceFile(argv[1]);
 // create zinput stream
 z_stream zs; memset(&zs, 0, sizeof(zs));
 if (inflateInit(&zs) != Z_OK) {
  cerr << "inflateInit() failed: " << zs.msg << endl;
  return 1;
 }
 for (size_t i = 0; i < data.size(); i++) {
  // 解压数据块
  uint8_t buf[8192];
  zs.next_in = data[i].data;
  zs.avail_in = data[i].csize;
  size_t remaining = data[i].size;
  while (remaining > 0) {
   zs.next_out = buf;
   zs.avail_out = min((size_t)sizeof(buf), remaining);
   int ret = inflate(&zs, Z_NO_FLUSH);
   if (ret != Z_OK && ret != Z_STREAM_END) {
    cerr << "inflate() failed: " << zs.msg << endl;
    return 1;
   }
   remaining -= zs.next_out - buf;
   cout << "inflated chunk of size " << (zs.next_out - buf) << endl;
  }
 }
 if (inflateEnd(&zs) != Z_OK) {
  cerr << "inflateEnd() failed: " << zs.msg << endl;
  return 1;
 }
 return 0;
}

在上述例子中,首先定义了一个DataBlock结构体,用来保存解压缩前后的数据。读取资源文件时,每次读取一个DataBlock,然后将其压缩前后的数据分别存储到结构体中。接着,使用zlib库中的inflate函数,对每个DataBlock进行解压。最后,可以在程序中使用解压后的数据。

在编写程序时,需要注意资源文件的格式和压缩算法的选择。如果使用较新的C++标准,也可以考虑使用文件流库中的压缩功能,实现更加方便快捷的压缩和解压缩操作。

  
  

评论区