将资源文件写入内存数据段

    有时候,我们经常需要给exe可执行文件附带一些资源文件(例如,皮肤,图片等一些资源),这些资源文件只能与exe独立放在硬盘上,这就带来了一些隐患,例如用户删除了或者修改了这些资源文件,就会引发可执行程序的非正常运行,或者无法运行,所以我们有必要把这些资源写进exe中。VS自带的添加资源方式维护起来很麻烦,所以要采用其他的办法。

    其实任何一个资源文件都是二进制的一组字节(Byte)流,如果我们把这些字节流写入到一个空间很大的变量中,不就可以了吗?因为一个char/unsigned char的大小就是一个byte的大小,所以我们可以将一个这些资源数据都写入到一个unsigned char[]数组中,然后调用这个数组的首地址不就可以得到资源文件在内存中的指针了吗?

    因为这个资源文件可能很大,所以我们单独的用一个.h或者.cpp文件来存放这个变量。

    下面就是一个可以将资源文件(可以是任何格式的文件,例如:txt,jpg,rar,zip等)中的字节流存放到一个unsigned char数组中的程序。


int _tmain(int argc, _TCHAR* argv[])
{
	if (argc == 1) return 0;

	HANDLE hRsrc = CreateFile(argv[1], GENERIC_WRITE | GENERIC_READ,
		0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hRsrc == INVALID_HANDLE_VALUE) return 0;

	TCHAR drive[_MAX_DRIVE] = {0};
	TCHAR dir[_MAX_DIR] = {0};
	TCHAR fname[_MAX_FNAME] = {0};
	TCHAR ext[_MAX_EXT] = {0};

	_tsplitpath_s(argv[1], drive, dir, fname, ext);
	TCHAR output[_MAX_DIR] = {0};
	if (argc == 2)
		_stprintf_s(output, _T("%s%s%s%s"), drive, dir, fname, _T(".cpp"));
	else
		_stprintf_s(output, _T("%s%s%s"), argv[2], fname, _T(".cpp"));

	HANDLE hCpp = CreateFile(output, GENERIC_WRITE|GENERIC_READ, 0,
		NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hCpp == INVALID_HANDLE_VALUE) return 0;

	printf("正在转换...\n");

	unsigned char ch = 0;
	DWORD dwReadSize = 0;
	DWORD dwWrittenSize = 0;
	DWORD dwFileSize = GetFileSize(hRsrc, NULL);

	char header[1024] = {0};
	sprintf_s(header, "%s%s%d%s%s%d%s","#include \"StdAfx.h\"\n", "int dataLen = ", dwFileSize + 20, 
		";\n", "unsigned char rsrcData[", dwFileSize + 20, "] = {\n");

	WriteFile(hCpp, header, strlen(header), &dwWrittenSize, NULL);

	char radihex[2] = {0};
	char buff[10] = {0};
	int cnt = 0;
	do
	{
		if(!ReadFile(hRsrc, &ch, sizeof(char), &dwReadSize, NULL))
			break;
		memset(radihex, 0, sizeof(radihex));
		memset(buff, 0, sizeof(buff));
		cnt++;
		if (cnt % 16 == 0 && cnt != 0)
		{
			sprintf_s(buff, "0x%02x,\n", ch);
			WriteFile(hCpp, buff, strlen(buff), &dwWrittenSize, NULL);
		}
		else if (cnt == dwFileSize + 1)
		{
			sprintf_s(buff, "0x%02x", ch);
			WriteFile(hCpp, buff, strlen(buff), &dwWrittenSize, NULL);
		}
		else
		{
			sprintf_s(buff, "0x%02x,", ch);
			WriteFile(hCpp, buff, strlen(buff), &dwWrittenSize, NULL);
		}

	} while (dwReadSize);

	char tail[1024] = {0};
	sprintf_s(tail, "%s", "\n};");
	WriteFile(hCpp, tail, strlen(tail), &dwWrittenSize, NULL);
	
	FlushFileBuffers(hCpp);
	CloseHandle(hRsrc);
	CloseHandle(hCpp);

	printf("转换完成!\n");
	Sleep(1000);

	return 0;
}

    这是控制台版的,需要在控制台传入两个参数,前面的参数是要转换的目标文件,后一个参数是输出路径(缺省的话就会输出到同级目录下)。

输出以后类似于这样的结果:

#include "StdAfx.h"
int dataLen = 1692;
unsigned char rsrcData[1692] = {
0x50,0x4b,0x03,0x04,0x14,0x00,0x00,0x00,0x08,0x00,0x60,0x5e,0xc6,0x44,0x53,0x30,
0xc6,0xe7,0x0c,0x02,0x00,0x00,0x56,0x04,0x00,0x00,0x08,0x00,0x00,0x00,0x6d,0x61,
0x69,0x6e,0x2e,0x78,0x6d,0x6c,0x85,0x54,0x4d,0x6f,0xd3,0x40,0x10,0x3d,0x83,0xc4,
0x7f,0x58,0x96,0x43,0x2f,0x71,0xfd,0x11,0x42,0x7b,0xb0,0x5b,0x91,0x92,0x88,0x43,
0xc5,0xb1,0x1c,0xd1,0xda,0x5e,0x3b,0x16,0x9b,0xdd,0x68,0xbd,0x21,0x6d,0xcf,0x88,
0x1e,0x22,0x04,0x12,0x5......
}

    然后在要使用该资源的位置声明引用这个两个变量:

// import resourse data
extern int dataLen;
extern unsigned char rsrcData[];
    dataLen为数据的长度,rsrcData为资源文字的指针地址,具体怎么用要看实际的需求了,很多库和api都支持从内存中读取数据。

    最后还附带一个可视化的转换工具:

   

    下载地址:

    点击打开链接

   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值