使用Windows 8新的压缩API进行数据压缩

昨天发布消费者预览版,今天安装好WIN8,第一时间就测试了这个看了很久的东西,开发者预览版没装,这玩意从开发者版本就有了,上个月翻MSDN时偶然看到,突然感觉太欢乐了,写出来了有必要分享一下。
由于我没装VS11(下到明年啊),直接下了个VB6精简版就写了,反正也没啥大不了,而且VB代码也能让更多人看懂。枚举类型和API翻译自MSDN给出的C++原形。

Private Enum COMPRESS_ALGORITHM_TYPE
COMPRESS_ALGORITHM_UNKNOWN = 1
COMPRESS_ALGORITHM_MSZIP = 2
COMPRESS_ALGORITHM_XPRESS = 3
COMPRESS_ALGORITHM_XPRESS_HUFF = 4
COMPRESS_ALGORITHM_LZMS = 5
End Enum
Private Enum COMPRESS_INFORMATION_CLASS
COMPRESS_INFORMATION_CLASS_INVALID = 0
COMPRESS_INFORMATION_CLASS_LEVEL 'XPRESS Only
COMPRESS_INFORMATION_CLASS_BLOCK_SIZE 'LZMS Only
End Enum

'压缩类API
Private Declare Function CreateCompressor& Lib "cabinet" (ByVal Algorithm As COMPRESS_ALGORITHM_TYPE, ByVal AllocationRoutines&, ByRef CompressorHandle&)
Private Declare Function QueryCompressorInformation& Lib "cabinet" (ByVal CompressorHandle&, ByVal CompressInformationClass As COMPRESS_INFORMATION_CLASS, ByVal CompressInformation&, ByVal CompressInformationSize&)
Private Declare Function SetCompressorInformation& Lib "cabinet" (ByVal CompressorHandle&, ByVal CompressInformationClass As COMPRESS_INFORMATION_CLASS, ByVal CompressInformation&, ByVal CompressInformationSize&)
Private Declare Function Compress& Lib "cabinet" (ByVal CompressorHandle&, ByVal UncompressedData&, ByVal UncompressedDataSize&, ByVal CompressedBuffer&, ByVal CompressedBufferSize&, ByRef CompressedDataSize&)
Private Declare Function CloseCompressor& Lib "cabinet" (ByVal CompressorHandle&)
'解压类API
Private Declare Function CreateDecompressor& Lib "cabinet" (ByVal Algorithm As COMPRESS_ALGORITHM_TYPE, ByVal AllocationRoutines&, ByRef DecompressorHandle&)
Private Declare Function QueryDecompressorInformation& Lib "cabinet" (ByVal DecompressorHandle&, ByVal CompressInformationClass As COMPRESS_INFORMATION_CLASS, ByVal CompressInformation&, ByVal CompressInformationSize&)
Private Declare Function SetDecompressorInformation& Lib "cabinet" (ByVal DecompressorHandle&, ByVal CompressInformationClass As COMPRESS_INFORMATION_CLASS, ByVal CompressInformation&, ByVal CompressInformationSize&)
Private Declare Function Decompress& Lib "cabinet" (ByVal DecompressorHandle&, ByVal CompressedData&, ByVal CompressedDataSize&, ByVal UncompressedBuffer&, ByVal UncompressedBufferSize&, ByRef UncompressedDataSize&)
Private Declare Function CloseDecompressor& Lib "cabinet" (ByVal DecompressorHandle&)

'压缩
Public Function Win8_Compressor(ByRef ByteIn() As Byte, ByRef Buffer() As Byte) As Boolean
Dim Handle&, Size&
If CreateCompressor(COMPRESS_ALGORITHM_MSZIP, 0, Handle) Then '创建压缩器句柄成功
Compress Handle, VarPtr(ByteIn(0)), UBound(ByteIn), 0, 0, Size '取得压缩需要的缓冲区大小
If Size > 0 Then
ReDim Buffer(Size - 1)
Compress Handle, VarPtr(ByteIn(0)), UBound(ByteIn), VarPtr(Buffer(0)), Size, Size '开始压缩
ReDim Preserve Buffer(Size) '实际压缩后的大小,清除无用的缓冲区。记得这里不能Size-1,因为解压器需要判断字节末尾有一个00的结束字节。
Win8_Compressor = True
End If
CloseCompressor Handle
End If
End Function

'解压
Public Function Win8_Decompressor(ByRef ByteIn() As Byte, ByRef Buffer() As Byte) As Boolean
Dim Handle&, Size&
If CreateDecompressor(COMPRESS_ALGORITHM_MSZIP, 0, Handle) Then '创建解压器成功
Decompress Handle, VarPtr(ByteIn(0)), UBound(ByteIn), 0, 0, Size '取得原始数据大小
If Size > 0 Then
ReDim Buffer(Size - 1)
Decompress Handle, VarPtr(ByteIn(0)), UBound(ByteIn), VarPtr(Buffer(0)), Size, Size '开始解压
Win8_Decompressor = True
End If
CloseDecompressor Handle
End If
End Function

Private Sub Form_Load()
On Error Resume Next
'WIN8压缩解压API实例,这里我用了MSZIP压缩算法。请在WIN8下运行。
Dim temp() As Byte,bf() As Byte
Open "c:\windows\prerelease.xml" For Binary Access Read As #1
ReDim temp(LOF(1) - 1)
Get #1, , temp()
Close #1

Win8_Compressor temp, bf '压缩数据
Kill "c:\eee.txt"
Open "c:\eee.txt" For Binary As #1
Put #1, , bf()
Close #1
Win8_Decompressor bf, temp '解压数据
Kill "c:\eee2.txt"
Open "c:\eee2.txt" For Binary As #1
Put #1, , temp()
Close #1
End Sub


压缩API有很多方面的用途,况且微软还给我们提供了那么多种算法,比如可以叠加压缩,再改那么几个字节,当加密也差不多了。。。
看到这好东西有人就会想说把这dll移植到xp、win7什么的,就像XMLLite那样,可很遗憾,cabinet这玩意连win7都移植不上去,具体原因就是这dll依赖win8的新版本ntdll...

WIN8中还加入了很多新的常用API,如:
CreateFile2,省略了CreateFile的一大堆无用参数。
SetCoalescableTimer,Windows消息计时器SetTimer的模糊版本,类似timeSetEvent的可设置精确度,不过消息计时器本来就不精确。。。
WaitOnAddress、WakeByAddressSingle、WakeByAddressAll,这3个玩意有点意思,WaitOnAddress类似WaitForSingleObject,不过这货不能等待一个call执行完毕然后返回,这货是等待一个内存地址指针的值为多少时才返回,支持1字节、2字节、4字节及8字节的值比对等,基本上编译器支持的dword啊、word啊之类的变量这函数都能使用。而WakeByAddressSingle及WakeByAddressAll分别是在另一个线程中唤醒一个WaitOnAddress等待的那个地址和唤醒所有WaitOnAddress等待的那个地址,让其继续执行不再等待。
以及还加入了一个叫“操作记录(Operation Recorder)”的API,可我测试这玩意貌似没啥作用,具体可在MSDN搜索“OperationStart”及“OperationEnd”。

最后再说一点,WIN8开始微软把用户层接口分为“Desktop apps”和“Metro apps”2种可使用的API,desktop就是大家熟悉的那些东西,metro则是新的一套,desktop的很多API都不能使用在metro上,而metro自己翻译了一部分desktop的API为metro专用版本及加入了一些metro专有api,当然也有不少API是desktop和metro共用的,如压缩API。

我个人而言对metro很蛋疼,至少我今天摸到现在都不懂如何删除or添加metro程序,自带的那些应用卡的一比,那个鸡巴应用商店给我的提示就一句话“Windows 应用商店目前不可用,请再试一次”,我去他娘的。好不容易安装了一个win8qq,可尼玛这能用么,E2180+2G内存给卡成幻灯片了,MS你这不是让ARM去 呢!


你可能感兴趣的:(Algorithm,windows,api,function,Class,buffer)