精确的概括是:
按名称从资源文件里面读和写二进制raw数据(raw在文件里面是按zlib压缩的形式存储的)
这样我就可以把一些文件资源用对应的api读入到内存的buffer中去,然后通过我的资源库压缩buffer再写入到资源文件里面去,下次真正调用的时候读出来解压还原到内存的buffer里面去使用。
下面要做的事情就是把游戏里面所有的资源文件都打包了。
只是目前还没有加上加密的算法
//看一段测试代码
void testFilestream()
{
FileStream filestream;
filestream.Open("aaa.bin", "r+");
char *p=0;
DWORD ln = 0;
char *src = "hello,a big boy";
filestream.Write("xxx.xxx", src, strlen(src));
filestream.Read("xxx.xxx", (void **)&p, ln);
printf("%s :%d\r\n", p, ln);
DELS(p);
filestream.Close();
}
结果:
hello,a big boy :15
请按任意键继续. . .
源码如下:
/************************************************************************/
/* 按命名从资源文件里面读和写raw数据(raw在文件里面是按zlib压缩的形式存储的)
/************************************************************************/
#pragma once
#ifndef FILESTREAM_H
#define FILESTREAM_H
#include <stdio.h>
#include <WTypes.h>
#include <string>
#include <assert.h>
#include "../include/zlib.h"
#pragma comment(lib,"../lib/zdll.lib")
namespace LK3D
{
class FileStream;
//////////////////////////////////////////////////////////////////////////////////////
// 文件或数据流(不支持同时读写多个数据区,只能一次对FileStream的一个数据区进行读写操作)
class FileDataStreamBuffer
{
private:
DWORD zipbuflen; //zip raw buffer len
void * zipbuf; //zip raw buffer 压缩字节流
//按照buflen重新分配空间
void realloc();
DWORD srcbuflen; //source raw buffer len
std::string dataname; //该数据流的名字
public:
DWORD GetSrcBufLen();
//构造
FileDataStreamBuffer(const char *dname);
//析构
~FileDataStreamBuffer();
//写字节,写之前一定要设定dataname
DWORD WriteBytes(const void *from,DWORD len);
//读字节,写之前一定要设定dataname
DWORD ReadBytes(void *to);
//debug
void DumpBuffer();
DWORD GetLen() const; //总长度,是计算出来的
bool operator ==(const FileDataStreamBuffer &other) const;
friend class FileStream;
};
class FileStream
{
FILE *pFile;
private:
//写文件包,写之前一定要设定filebuf.dataname
DWORD Write(FileDataStreamBuffer& filebuf);
//读文件包,读之前一定要设定filebuf.dataname
DWORD Read(FileDataStreamBuffer& filebuf);
public:
FileStream(void);
~FileStream(void);
//打开一个文档
DWORD Open(const char* archive,const char *mode);
//写某个数据段落
DWORD Write(const char* dname, const void *from, DWORD len);
//读取某个数据段落
DWORD Read(const char* dname, void **to, DWORD &len);
//关闭文件流
void Close();
friend void testFileStream();
};
void testFileStream();
void testFileStream1();
}
#endif
//FileStream.cpp
#include "FileStream.h"
#ifndef DEL
#define DEL(p) { if(p) { delete (p); (p) = NULL; } }
#endif
#ifndef DELS
#define DELS(p) { if(p) { delete[] (p); (p) = NULL; } }
#endif
#ifndef RELEASE
#define RELEASE(p) { if(p) { (p)->Release(); (p) = NULL; } }
#endif
using namespace LK3D;
FileDataStreamBuffer::FileDataStreamBuffer(const char *dname)
{
zipbuflen = 0;
zipbuf = 0;
srcbuflen = 0;
dataname = dname;
}
DWORD FileDataStreamBuffer::GetSrcBufLen()
{
return srcbuflen;
}
FileDataStreamBuffer::~FileDataStreamBuffer()
{
DELS(zipbuf);
}
void FileDataStreamBuffer::realloc()
{
DELS(zipbuf);
zipbuf = new char[zipbuflen];
}
bool FileDataStreamBuffer::operator ==(const FileDataStreamBuffer &other) const
{
return GetLen() == other.GetLen() &&
dataname == other.dataname &&
zipbuflen == other.zipbuflen &&
memcmp((const char *)zipbuf, (const char *)other.zipbuf, zipbuflen) == 0 &&
srcbuflen == other.srcbuflen;
}
DWORD FileDataStreamBuffer::GetLen() const
{
// 文件名长度占位 文件名长度 srcbuf长度占位 zipbuf长度占位 zipbuf长度
return sizeof(DWORD) + (DWORD)dataname.size() + sizeof(DWORD) + sizeof(DWORD) + zipbuflen;
}
//写字节
DWORD FileDataStreamBuffer::WriteBytes(const void *from,DWORD len)
{
if(dataname.empty())
return 0; //还未给要写入的部分命名
if(!from)
return 0;
//记录原字节数据区的长度
srcbuflen = len;
//重新分配zipbuf的空间
//DELS(zipbuf);
zipbuflen =(DWORD)(len+ (len * 0.1) + 12); //这是个公式,官方网站上提供的,预留的最小的压缩空间的大小
realloc();
//压缩原数据到zipbuf中去
compress2((Bytef*)zipbuf,(uLongf*)&zipbuflen,(const Bytef*)from,(uLongf)srcbuflen, Z_DEFAULT_COMPRESSION);
return len;
}
//读字节
DWORD FileDataStreamBuffer::ReadBytes(void *to)
{
//if(dataname.empty())
// return 0; //还未给要读取的部分命名
if(!to)
return 0;
uncompress((Bytef*)to, (uLongf *)&srcbuflen, (const Bytef*)zipbuf, (uLong)zipbuflen);
return zipbuflen;
}
void FileDataStreamBuffer::DumpBuffer()
{
DWORD len = zipbuflen;
printf("Buffer: size=%d", len);
if (len > 0)
{
printf(" [ ");
const UCHAR* pBuf = (const UCHAR*) zipbuf;
for (DWORD i = 0; i < len; ++i)
printf("%02X ", pBuf[i]);
printf("]");
}
printf("\n");
}
FileStream::FileStream(void)
{
pFile = 0;
}
FileStream::~FileStream(void)
{
Close();
}
//打开一个文档
DWORD FileStream::Open(const char* archive,const char *mode)
{
pFile = fopen(archive, mode);
assert(pFile);
return 0;
}
//写文件包
DWORD FileStream::Write(FileDataStreamBuffer& filebuf)
{
if(filebuf.dataname.empty())
{
return 0; //指定要读取的数据区的名称
}
DWORD writebytes = 0;
//写入文件名的长度占位
DWORD filenamelen = (DWORD)filebuf.dataname.size();
writebytes+=(DWORD)(fwrite(&filenamelen, sizeof(DWORD), 1, pFile) * sizeof(DWORD));
//写入文件名
writebytes+=(DWORD)(fwrite(filebuf.dataname.c_str(), sizeof(char), filebuf.dataname.size(), pFile) * sizeof(char));
//写入srcbuf长度的占位
writebytes+=(DWORD)(fwrite(&filebuf.srcbuflen, sizeof(DWORD), 1, pFile) * sizeof(DWORD));
//写入zipbuf的长度占位
writebytes+=(DWORD)(fwrite(&filebuf.zipbuflen, sizeof(DWORD), 1, pFile) * sizeof(DWORD));
//写入zipbuf
writebytes+=(DWORD)(fwrite(filebuf.zipbuf, sizeof(char), filebuf.zipbuflen, pFile) * sizeof(char));
return writebytes;
}
//读文件包
DWORD FileStream::Read(FileDataStreamBuffer& filebuf)
{
if(filebuf.dataname.empty())
{
return 0; //指定要读取的数据区的名称
}
//从文件头开始
rewind(pFile);
char filename[100]; //文件名预留100应该足够了
ZeroMemory(filename, 100);
//实际读取的数量
DWORD readbytes = 0;
bool founded = false;
// bool bt = false;
// fseek(filebuf,1000, SEEK_CUR);
while(filebuf.dataname != filename)
{
//读入文件名长度的占位
DWORD filenamelen = 0;
readbytes += (DWORD)(fread(&filenamelen, sizeof(DWORD), 1, pFile) * sizeof(DWORD));
if(readbytes == 0)
break; //已经无法读取数据了,说明已经eof了
//读入文件名
readbytes += (DWORD)(fread(&filename, sizeof(char), filenamelen, pFile) * sizeof(char));
//读入srcbuf长度占位
readbytes += (DWORD)(fread(&filebuf.srcbuflen, sizeof(DWORD), 1, pFile) * sizeof(DWORD));
//读入zipbuf长度占位
readbytes += (DWORD)(fread(&filebuf.zipbuflen, sizeof(DWORD), 1, pFile) * sizeof(DWORD));
if(filebuf.dataname == filename)
{
//重新分配可以装载数据的空间
filebuf.realloc();
readbytes += (DWORD)(fread(filebuf.zipbuf, sizeof(char), filebuf.zipbuflen, pFile) * sizeof(char));
founded = true;
break;
}
else
{
readbytes = 0; //重新计数
//不是要找的data直接后移filebuf.zipbuflen
fseek(pFile, filebuf.zipbuflen, SEEK_CUR);
filebuf.zipbuflen = 0; //读取的zipbuffer长度也清0,作废处理
filebuf.srcbuflen = 0; //读取的srcbuffer长度也清0,作废处理
}
ZeroMemory(filename, 100);
}
if(founded)
return readbytes; //返回实际读取的字节数
else
return 0; //读取失败了
}
//关闭文件流
void FileStream::Close()
{
if(pFile)
{
fclose(pFile);
pFile = 0;
}
}
DWORD FileStream::Write(const char* dname, const void *from,DWORD len)
{
FileDataStreamBuffer streambuf(dname);
if(!streambuf.WriteBytes(from, len))
return 0;
return Write(streambuf);
}
DWORD FileStream::Read(const char* dname, void **to, DWORD &len)
{
FileDataStreamBuffer streambuf(dname);
if(Read(streambuf))
{
if(*to)
{
printf("warning, 销毁接收缓冲...");
DELS(*to)
}
len = streambuf.GetSrcBufLen();
*to = new char[len];
streambuf.ReadBytes(*to);
return len;
}
else
return 0;
}
void LK3D::testFileStream()
{
FileDataStreamBuffer f1("file1.txt");
char *str1 ="one 111";
f1.WriteBytes(str1, (DWORD)strlen(str1));
FileDataStreamBuffer f2("file2.txt");
char *str2 ="a111111111111111111b";
f2.WriteBytes(str2, (DWORD)strlen(str2));
FileStream stream;
//写
stream.Open("aaa.bin", "wb");
DWORD d1 = stream.Write(f1);
DWORD d2 = stream.Write(f2);
assert(d1 == f1.GetLen());
assert(d2 == f2.GetLen());
stream.Close();
f2.DumpBuffer();
//读
FileStream stream1;
stream1.Open("aaa.bin", "rb");
FileDataStreamBuffer val_bf("file2.txt");
DWORD vd2 = stream1.Read(val_bf);
stream1.Close();
val_bf.DumpBuffer();
if(vd2)
{
assert(vd2 == d2);
assert(f2 == val_bf);
char *c = new char[val_bf.GetSrcBufLen() +1];
ZeroMemory(c, val_bf.GetSrcBufLen() +1);
val_bf.ReadBytes(c);
printf("%s \r\n", c);
} else
{
printf("没找到数据\r\n");
}
}
void LK3D::testFileStream1()
{
FileStream filestream;
filestream.Open("aaa.bin", "r+");
char *p=0;
DWORD ln = 0;
char *src = "hello,a big boy";
filestream.Write("xxx.xxx", src, (DWORD)strlen(src));
filestream.Read("xxx.xxx", (void **)&p, ln);
printf("%s :%d\r\n", p, ln);
DELS(p);
filestream.Close();
}