已经 测 试 通过

// testZlib.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

//#define BOOST_IOSTREAMS_SOURCE
#include <boost/static_assert.hpp>
#include <boost/iostreams/filter/zlib.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/counter.hpp>
#include <boost/iostreams/device/back_inserter.hpp>
#include <boost/array.hpp>
#include <boost/crc.hpp>
//#include <boost/../libs/iostreams/src/zlib.cpp>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <algorithm>
typedef std::vector<char>	DataStream;

using namespace std;
const DWORD dwVersion = MAKELONG(MAKEWORD('z', 'y'), MAKEWORD('z', 'f'));
struct PacketFileHeader
{
	DWORD	version;
	DWORD	dwFileHeaderPos;		//FileHeader 开始的偏移位置
	DWORD	dwTotalFile;			//保存了多少个文件.在文件头之后,都是每一个文件的内容,文件结尾保存文件的名字和原来大小及位置
};
const int packetFileHeaderLenght = sizeof(PacketFileHeader);

struct FileHeader
{
	char	fileName[32];
	DWORD	dwOriginFileSize;			//原来文件的大小
	DWORD	dwFileOffset;				//在压缩包中文件的偏移 
	DWORD	dwFileSize;					//压缩后的大小。
	DWORD	crc;

};
const int fileHeaderSize = sizeof(FileHeader);

const std::string strDir("E:\\QQ资源\\Data\\Head\\");
bool changeName(const char* src, const char* dst)
{
	char buf[1024];
	_snprintf(buf, 1024, "rename %s%s %s", strDir.c_str(), src, dst);
	system(buf);
	return true;
}
class CUnPacketFile
{
	std::string			m_strFilename;
	HANDLE				m_hReader;
	std::vector<FileHeader>	m_FileHeaders;
	char*				m_buffer;
	bool				m_bValid;
public:
	CUnPacketFile() : m_hReader(INVALID_HANDLE_VALUE) , m_buffer(NULL), m_bValid(false)
	{
	}
	~CUnPacketFile()
	{
		if (m_hReader != INVALID_HANDLE_VALUE)
		{
			CloseHandle(m_hReader);
			m_hReader = INVALID_HANDLE_VALUE;
		}
	}
	DWORD GetUnFileSize(const char* pszFileName) //如果存在这个文件,返回大于0的值(需要解压缩的最小空间),否则返回0
	{
		if (!m_bValid)
		{
			return 0;
		}
		for (size_t i = 0; i < m_FileHeaders.size(); ++i)
		{
			if (strcmp(pszFileName, m_FileHeaders[i].fileName) == 0)
			{
				return m_FileHeaders[i].dwOriginFileSize;
			}
		}
		return 0;
	}
	bool UnpackFile(const char* pszFileName, void* pBuffer, DWORD bufSize)
	{
		DWORD fileSize = GetUnFileSize(pszFileName); //得到文件原始大小。
		if (fileSize == 0)
		{
			return false;
		}
		if (bufSize < fileSize)
		{
			return false;
		}

		FileHeader* pHeader = NULL;
		for (size_t i = 0; i < m_FileHeaders.size(); ++i)
		{
			if (strcmp(pszFileName, m_FileHeaders[i].fileName) == 0)
			{
				pHeader = &m_FileHeaders[i];
				break;
			}
		}
		if (pHeader == NULL)
		{
			assert(0);
			return false;
		}

		char* pStart = m_buffer + pHeader->dwFileOffset;
		DWORD dwSize = pHeader->dwFileSize;
		std::vector<char> out;
		boost::iostreams::copy(boost::make_iterator_range(pStart, pStart + dwSize),
			boost::iostreams::filtering_ostream(boost::iostreams::zlib_decompressor() | boost::iostreams::back_inserter(out)));
		if (out.size() > bufSize)
		{
			return false;
		}
		memcpy(pBuffer, &out[0], out.size());
		
		return true;

	}
	bool OpenPacket(const char* strPacketFileName)
	{
		m_bValid = false;
		m_strFilename = strPacketFileName;
		m_hReader = CreateFileA(m_strFilename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
		if (m_hReader == INVALID_HANDLE_VALUE)
		{
			return false;
		}
		DWORD dwRead = 0;
		DWORD dwHighSize, dwLowSize;
		dwLowSize = GetFileSize(m_hReader, &dwHighSize);
		if (dwHighSize != 0)
		{
			//文件太大,暂时不支持
			CloseHandle(m_hReader);
			m_hReader = INVALID_HANDLE_VALUE;
			return false;
		}
		try
		{
			m_buffer = new char[dwLowSize];
		}
		catch(...)
		{
			m_buffer = NULL;
		}

		if (m_buffer == NULL)
		{
			CloseHandle(m_hReader);
			m_hReader = INVALID_HANDLE_VALUE;
			return false;
		}
		if(!ReadFile(m_hReader, m_buffer, dwLowSize, &dwRead, NULL) || (dwRead != dwLowSize)) //读入整个文件
		{
			CloseHandle(m_hReader);
			m_hReader = INVALID_HANDLE_VALUE;
			return false;
		}
		
		PacketFileHeader* pFileHeader = (PacketFileHeader*)m_buffer;
		if (pFileHeader->version != dwVersion)
		{
			CloseHandle(m_hReader);
			m_hReader = INVALID_HANDLE_VALUE;
			return false;
		}

	
		if (dwLowSize != (pFileHeader->dwFileHeaderPos + sizeof(FileHeader) * pFileHeader->dwTotalFile))		//校验文件的长度。

		{
			CloseHandle(m_hReader);
			m_hReader = INVALID_HANDLE_VALUE;

			return false;
		}
		FileHeader* pFh = (FileHeader*)(m_buffer + pFileHeader->dwFileHeaderPos);
		m_FileHeaders.clear();
		boost::crc_32_type crc;
		for (DWORD i = 0; i < pFileHeader->dwTotalFile; ++i)
		{
			//crc检验
			crc.reset();
			crc.process_bytes(m_buffer + pFh->dwFileOffset, pFh->dwFileSize);
			if (crc.checksum() != pFh->crc)
			{
				CloseHandle(m_hReader);
				m_hReader = INVALID_HANDLE_VALUE;
				return false;
			}
			m_FileHeaders.push_back(*pFh++);
		}
		DWORD dwCheck = (const char*)pFh - m_buffer;
		if(dwCheck != dwLowSize)
		{
			return false;
		}

		m_bValid = true;
		return true;
	}
};
bool PacketAFile(const char* fileName, DataStream& ds, FileHeader& fh)
{
	memset(&fh, 0, sizeof(FileHeader));
	strcpy(fh.fileName, fileName);
	std::string strFullPathName = strDir;
	strFullPathName += fileName;
	HANDLE hFile = CreateFileA(strFullPathName.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		return false;
	}
	DWORD dwHigh = 0;
	DWORD dwFileSize = GetFileSize(hFile, &dwHigh);
	if (dwHigh != 0)
	{
		CloseHandle(hFile);
		return false;
	}
	char *pBuffer = new char[dwFileSize];
	DWORD dwFileRead = 0;
	if(!ReadFile(hFile, pBuffer, dwFileSize, &dwFileRead, NULL))
	{
		delete[] pBuffer;
		CloseHandle(hFile);
		return false;
	}
	if (dwFileRead != dwFileSize)
	{
		delete[] pBuffer;
		CloseHandle(hFile);
		return false;
	}
	CloseHandle(hFile);
	ds.resize(0);
	boost::iostreams::copy(boost::make_iterator_range(pBuffer, pBuffer + dwFileRead),
		boost::iostreams::filtering_ostream(boost::iostreams::zlib_compressor() | boost::iostreams::back_inserter(ds)));

	fh.dwOriginFileSize = dwFileSize;
	fh.dwFileSize = ds.size();

	boost::crc_32_type crc;
	crc.process_bytes(&ds[0], ds.size());
	fh.crc = crc.checksum();
	//偏址由调用者填写。
	delete[] pBuffer;
	return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
	char tmpBuf[32];

	HANDLE hWriteFile = CreateFileA("d:\\res.dat", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if(hWriteFile == INVALID_HANDLE_VALUE)
	{
		std::cout << "Write file failed.\n";
		return -1;
	}

	PacketFileHeader pfh;
	DWORD dwFileWritten = 0;
	if(!WriteFile(hWriteFile, &pfh, packetFileHeaderLenght, &dwFileWritten, NULL) || (dwFileWritten != packetFileHeaderLenght))
	{
		std::cout << "write file header failed.\n";
		return -1;
	}
	int offset = packetFileHeaderLenght; //已经计入文件包的头部。
	DataStream ds;
	std::vector<FileHeader> fileHeaderArray;
	FileHeader fh;
	for (int i = 1; i <= 254; ++i)
	{
		_snprintf(tmpBuf, 32, "%d.png", i);
		if (PacketAFile(tmpBuf, ds, fh)) //打包png
		{
			fh.dwFileOffset = offset;
			offset += fh.dwFileSize;
			if(!WriteFile(hWriteFile, &ds[0], ds.size(), &dwFileWritten, NULL) || (dwFileWritten != ds.size()))
			{
				std::cout << "write file " << tmpBuf << "failed.\n";
				return -1;
			}

			fileHeaderArray.push_back(fh);
		}
		else 
		{
			std::cout << "error:" << tmpBuf << std::endl;
			return -1;
		}

		_snprintf(tmpBuf, 32, "%d_16.bmp", i);
		if (PacketAFile(tmpBuf, ds, fh))	//打包bmp
		{
			fh.dwFileOffset = offset;
			offset += fh.dwFileSize;
			//out.write(&ds[0], ds.size());
			if(!WriteFile(hWriteFile, &ds[0], ds.size(), &dwFileWritten, NULL) || (dwFileWritten != ds.size()))
			{
				std::cout << "write file " << tmpBuf << "failed.\n";
				return -1;
			}

			fileHeaderArray.push_back(fh);
		}
		else 
		{
			std::cout << "error:" << tmpBuf << std::endl;
			return -1;
		}

	}
	//if (PacketAFile("test.txt", ds, fh)) //写一个测试文件 
	//{
	//	fh.dwFileOffset = offset;
	//	offset += fh.dwFileSize;
	//	if(!WriteFile(hWriteFile, &ds[0], ds.size(), &dwFileWritten, NULL) || (dwFileWritten != ds.size()))
	//	{
	//		std::cout << "write file " << tmpBuf << "failed.\n";
	//		return -1;
	//	}

	//	fileHeaderArray.push_back(fh);
	//}
	//else 
	//{
	//	std::cout << "error:" << tmpBuf << std::endl;
	//	return -1;
	//}

	//写每个文件的文件头
	for (int i = 0; i < fileHeaderArray.size(); ++i)
	{
		if(!WriteFile(hWriteFile, &fileHeaderArray[i], fileHeaderSize, &dwFileWritten, NULL) || (dwFileWritten != fileHeaderSize))
		{
			std::cout << "write file header info failed.\n";
			return -1;
		}

	}
	pfh.version = dwVersion;
	pfh.dwTotalFile = fileHeaderArray.size();
	pfh.dwFileHeaderPos = offset;

	SetFilePointer(hWriteFile, 0, 0, FILE_BEGIN);
	WriteFile(hWriteFile, &pfh, packetFileHeaderLenght, &dwFileWritten, NULL);
	if (dwFileWritten != packetFileHeaderLenght)
	{
		std::cout << "修改文件头失败" << std::endl;
		return -1;
	}
	CloseHandle(hWriteFile);

	CUnPacketFile upf;
	bool bSuccess = upf.OpenPacket("d:\\res.dat");
	if (bSuccess)
	{
		DWORD dwSize = upf.GetUnFileSize("211.png");
		if (dwSize)
		{
			unsigned char* pBuf = new unsigned char[dwSize];
			hWriteFile = CreateFileA("d:\\211.png", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
			DWORD dwWrite = 0;
			if(upf.UnpackFile("211.png", pBuf, dwSize))
			{
				WriteFile(hWriteFile, pBuf, dwSize, &dwFileWritten, NULL);

			}
			else
			{
				std::cout << "写png文件失败!" << std::endl;		
			}
			delete[] pBuf;
			CloseHandle(hWriteFile);
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值