使用zlib压缩IStream流
来源:互联网 发布:c4.5决策树算法python 编辑:程序博客网 时间:2024/05/22 09:47
使用zlib压缩IStream流 by sdragon
比较完善的一个压缩流类,已经能够使用了。欢迎提出意见,具体使用方法,看看代码吧。
头文件:
#ifndef CompressStreamH
#define CompressStreamH
//---------------------------------------------------------------------------
#include <windows.h>
#include <objbase.h> //IStorage, IStream
#include <atl/atlbase.h> //CComPtr, CComBSTR
namespace zlib
{
#include <zlib/zlib.h>
}using namespace zlib;
#pragma link "zlib.lib"
#include <cstdio>
#include <vector>
#include <memory>
#include <cassert>
#include <stdint.h>
using namespace std;
#pragma pack(push, 1)
struct Z_DATAINFO
{
uint16_t version;
int16_t level;
uint32_t size;
uint32_t src_size;
uint32_t crc32;
};
#ifndef Z_CRC32_VERIFY_ERROR
#define Z_CRC32_VERIFY_ERROR = -128
#endif
#pragma pack(pop)
class CCompressStream
{
private:
const static DWORD STATE_NONE = 0;
const static DWORD STATE_DEFLATE = 1;
const static DWORD STATE_INFLATE = 2;
const static DWORD BUFFER_SIZE = 1024*8;
public:
CCompressStream();
CCompressStream(CComPtr<IStream>& lpStream);
~CCompressStream();
int BeginDeflate(int level = Z_DEFAULT_COMPRESSION);
int EndDeflate();
int BeginInflate();
int EndInflate();
int Write(BYTE *lpData, DWORD dwSize, LPDWORD pWritten);
int Read(BYTE *lpData, DWORD dwSize, LPDWORD pRead);
int SaveToFile(const char* fname);
int LoadFromFile(const char* fname);
IStream** operator&(){ return &m_lpStream; }
private:
CComPtr<IStream> m_lpStream;
DWORD m_dwState;
z_stream m_zstm;
vector<char> m_buffer;
Z_DATAINFO m_info;
};
//---------------------------------------------------------------------------
#endif
源文件:
//---------------------------------------------------------------------------
#pragma hdrstop
#include "CompressStream.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
CCompressStream::CCompressStream()
:m_dwState(STATE_NONE)
{
}
CCompressStream::CCompressStream(CComPtr<IStream>& lpStream)
:m_lpStream(lpStream), m_dwState(STATE_NONE)
{
}
CCompressStream::~CCompressStream()
{
assert(m_dwState == STATE_NONE);
}
int CCompressStream::BeginDeflate(int level)
{
assert(m_dwState == STATE_NONE);
int result = 0;
LARGE_INTEGER li = {sizeof(Z_DATAINFO)};
memset(&m_zstm, 0, sizeof(z_stream));
result = deflateInit(&m_zstm, level);
if (result == Z_OK)
{
m_dwState = STATE_DEFLATE;
m_lpStream->Seek(li, STREAM_SEEK_SET, NULL);
m_buffer.reserve(BUFFER_SIZE);
memset(&m_info, 0, sizeof(Z_DATAINFO));
m_info.version = ZLIB_VERNUM;
m_info.level = level;
m_info.crc32 = zlib::crc32(0, NULL, 0);
}
return result;
}
int CCompressStream::EndDeflate()
{
assert(m_dwState == STATE_DEFLATE);
//写入剩余缓冲区的数据
this->Write(NULL, 0, NULL);
//写入Z_DATAINFO信息
LARGE_INTEGER li = {0};
m_lpStream->Seek(li, STREAM_SEEK_SET, NULL);
m_lpStream->Write(&m_info, sizeof(m_info), NULL);
//清理环境
m_dwState = STATE_NONE;
m_buffer.swap(vector<char>());
return deflateEnd(&m_zstm);;
}
int CCompressStream::Write(BYTE *lpData, DWORD dwSize, LPDWORD pWritten)
{
assert(m_dwState == STATE_DEFLATE);
//Z_NO_FLUSH 表示可能还有数据,Z_FINISH 表示不再有数据了,处理完
//数据后就可以结束了。这里如果(dwSize == 0),表示没有数据了,处理
//完缓冲内的数据后结束。
int flush = dwSize ? Z_NO_FLUSH : Z_FINISH;
size_t szdata = 0; //compress data size
DWORD written = 0; //for stream write
int result = 0;
//计算crc32校验值
if(dwSize != 0)m_info.crc32 = zlib::crc32(m_info.crc32, lpData, dwSize);
//统计源数据长度
m_info.src_size += dwSize;
m_zstm.avail_in = dwSize;
m_zstm.next_in = lpData;
do
{
m_zstm.avail_out = BUFFER_SIZE;
m_zstm.next_out = &m_buffer.front();
result = deflate(&m_zstm, flush);
assert(result != Z_STREAM_ERROR);
szdata = BUFFER_SIZE - m_zstm.avail_out;
m_info.size += szdata; //统计压缩数据长度
m_lpStream->Write(&m_buffer.front(), szdata, &written);
if(pWritten)*pWritten = written;
if(written != szdata)//检测可能出现的数据写入错误
{
return Z_ERRNO;
}
}while(m_zstm.avail_out == 0); //avail_out == 0 表示可能
//还有数据没有得到压缩
assert(m_zstm.avail_in == 0); // all input will be used
return result;
}
int CCompressStream::BeginInflate()
{
assert(m_dwState == STATE_NONE);
int result = 0;
LARGE_INTEGER li = {0};
memset(&m_zstm, 0, sizeof(z_stream));
result = inflateInit(&m_zstm);
if (result == Z_OK)
{
DWORD dwRead = 0;
m_dwState = STATE_INFLATE;
m_lpStream->Seek(li, STREAM_SEEK_SET, NULL);
m_lpStream->Read(&m_info, sizeof(m_info), &dwRead);
assert(dwRead != 0);
m_buffer.reserve(BUFFER_SIZE);
}
return result;
}
int CCompressStream::EndInflate()
{
assert(m_dwState == STATE_INFLATE);
m_dwState = STATE_NONE;
m_buffer.swap(vector<char>());
return inflateEnd(&m_zstm);;
}
int CCompressStream::Read(BYTE *lpData, DWORD dwSize, LPDWORD pRead)
{
assert(m_dwState == STATE_INFLATE);
assert(dwSize != 0);
int result = 0;
//avail_in == 0 表示当前数据已经解压完毕,可以读入新的压缩数据
if(m_zstm.avail_in == 0)
{
DWORD dwRead = 0;
m_lpStream->Read(&m_buffer.front(), BUFFER_SIZE, &dwRead);
if(dwRead == 0)
{
return Z_DATA_ERROR;
}
m_zstm.avail_in = dwRead;
m_zstm.next_in = &m_buffer.front();
}
m_zstm.avail_out = dwSize;
m_zstm.next_out = lpData;
result = inflate(&m_zstm, Z_NO_FLUSH);
*pRead = dwSize - m_zstm.avail_out;
//Z_STREAM_END 表示流中的压缩数据已经完全读取,解压后就可以关闭了
//所以这里返回Z_OK,进行最后一次解压
return result == Z_STREAM_END ? Z_OK : result;
}
int CCompressStream::SaveToFile(const char* fname)
{
char buf[BUFFER_SIZE] = {0};
DWORD size = 0;
int result = 0;
FILE* f = fopen(fname, "wb");
if(!f)return Z_ERRNO;
result = this->BeginInflate();
if(result == Z_OK)
{
while(this->Read(buf, BUFFER_SIZE, &size) == Z_OK)
{
if((fwrite(buf, 1, size, f) != size) || ferror(f))
{
fclose(f);
this->EndInflate();
return Z_ERRNO;
}
}
fclose(f);
result = this->EndInflate();
}
return result;
}
int CCompressStream::LoadFromFile(const char* fname)
{
char buf[BUFFER_SIZE] = {0};
size_t size = 0;
int result = 0;
FILE *f = fopen(fname, "rb");
if(!f)return Z_ERRNO;
result = this->BeginDeflate();
if(result != Z_OK)return result;
do
{
size = fread(buf, 1, BUFFER_SIZE, f);
if (ferror(f))goto LOCAL_ERROR;
result = this->Write(buf, size, NULL);
if(result != Z_OK)goto LOCAL_ERROR;
}while(!feof(f));
fclose(f);
return this->EndDeflate();
LOCAL_ERROR:
fclose(f);
this->EndDeflate();
return Z_ERRNO;
}
测试代码:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
_di_IStorage pstg;
CCompressStream pstm;
HRESULT hr = StgCreateDocfile(
L"DocFile.stg",
STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE|STGM_DIRECT,
0,
&pstg);
if(SUCCEEDED(hr))
{
hr = pstg->CreateStream(
L"MainElement",
STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE|STGM_DIRECT,
0, 0,
&pstm);
if(SUCCEEDED(hr))
{
print(pstm.LoadFromFile("未命名.bmp")); //将文件导入流
print(pstm.SaveToFile("未命名2.bmp")); //将文件导出到文件
}
}
}
- 使用zlib压缩IStream流
- 使用zlib压缩IStream流
- 使用zlib压缩IStream流2
- 使用zlib压缩IStream流2
- zlib的使用-压缩
- Zlib压缩类库使用
- 使用zlib压缩解压缩文件
- 使用zlib压缩/解压文件
- 使用Zlib实现压缩和解压缩
- 使用Zlib实现压缩和解压缩
- 使用Zlib实现压缩和解压缩
- delphi Zlib 流压缩解压
- delphi Zlib 流压缩解压
- VC GDI+ 窗口截图内存BMP转JPG,压缩、JPG再转IStream流,IStream流再转 BYTE
- [Zlib]_[初级]_[使用zlib库压缩目录]
- 使用zlib库进行短文本压缩
- 压缩解压缩的函数库zlib的使用
- 转贴: 【python】使用zlib进行压缩解压
- iostream 与 iostream.h 的区别
- Windows操作系统实习之读者-写者问题
- 微型lua
- WCF中Service Configuration Editor的使用方法
- 用 AppFramework 替换 Discuz!NT 的数据库访问层
- 使用zlib压缩IStream流
- 项目组开发原则
- asp.net页面间数据传递(总结篇)
- 使用zlib压缩IStream流2
- auto_array
- 图解Exchange2007 安装
- 用了整整一个晚上,就因为byte & int
- MBR简介
- fast_cast数据类型转换