前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >VBA解压缩ZIP文件03——解压准备工作

VBA解压缩ZIP文件03——解压准备工作

作者头像
xyj
发布2020-07-28 14:31:54
1.4K0
发布2020-07-28 14:31:54
举报
文章被收录于专栏:VBA 学习VBA 学习

要解压缩ZIP文件,所以肯定需要读写文件的功能,为了方便,把VBA中对文件的读写功能进行一个简单的封装,方便使用。

ZIP文件压缩后,保存数据使用的最小单位是bit,注意不是Byte,计算机的1Byte=8bit,正常在VBA中操作的最小单位是Byte,为了方便读取bit位的数据,写几个简单的函数。

01

CFile文件读写

主要是使用类模块对文件操作Open、Put、Get等关键字的简单封装,这样使用起来就更加的方便。

代码语言:javascript
复制
Public Enum OpenAccess
    O_RDONLY
    O_WRONLY
    O_RDWR
End Enum

Public Enum SeekPos
    OriginF
    CurrentF
    EndF
End Enum

'注意大文件long类型会溢出
Private lFileLen As Long
Private num_file As Integer

'写入文件
Function WriteFile(b() As Byte) As Long
    Put #num_file, , b
End Function

'读取len(b)个byte
Function Read(b() As Byte) As Long
    Dim ilen As Long
    ilen = UBound(b) - LBound(b) + 1

    Dim iseek As Long
    iseek = VBA.Seek(num_file)
    If iseek + ilen > lFileLen Then
        ilen = lFileLen - iseek + 1
    End If

    Get #num_file, , b

    Read = ilen
End Function
'读取一个2Byte的整数
Function ReadInteger() As Integer
    Dim i As Integer
    Get #num_file, , i
    ReadInteger = i
End Function
'读取1个4Byte的整数
Function ReadLong() As Long
    Dim i As Long
    Get #num_file, , i
    ReadLong = i
End Function

'在offset处开始读取
Function ReadAt(b() As Byte, offset As Long) As Long
    SeekFile offset, 0
    ReadAt = Read(b)
End Function

'设置读取的位置
Function SeekFile(offset As Long, whence As SeekPos) As Long
    Dim iseek As Long
    iseek = VBA.Seek(num_file)

    'vba Seek是下标1开始
    If whence = SeekPos.OriginF Then
        iseek = 1 + offset
    ElseIf whence = SeekPos.CurrentF Then
        iseek = iseek + offset
    Else
        iseek = 1 + lFileLen - offset
    End If

    Seek #num_file, iseek

    SeekFile = iseek
End Function

'以字节方式读取文本
Function OpenFile(Filename As String, Optional m As OpenAccess = OpenAccess.O_RDWR) As Long
    '避免多次调用OpenFile的时候,前面的文件未关闭
    If num_file Then Close #num_file

    num_file = VBA.FreeFile

    Select Case m
        Case OpenAccess.O_RDONLY
        Open Filename For Binary Access Read As #num_file

        Case OpenAccess.O_WRONLY
        Open Filename For Binary Access Write As #num_file

        Case OpenAccess.O_RDWR
        Open Filename For Binary Access Read Write As #num_file

        Case Else

    End Select


    lFileLen = VBA.FileLen(Filename)
End Function

Function CloseFile()
    Close #num_file
End Function

Private Sub Class_Terminate()
    CloseFile
End Sub

02

bit位操作

计算机中1Byte=8bit,bit的排列顺序和数学中的个位、十位、百位……是一样的:

解压ZIP的过程中,需要不停的从压缩数据的Byte数组中读取需要的bit,实现几个简单的函数:

代码语言:javascript
复制
'取某一位的Bit
Function GetBitFromByte(b As Byte, ZeroBaseIndex As Long) As Long
    GetBitFromByte = VBA.CLng(b) And (2 ^ ZeroBaseIndex)
    If GetBitFromByte > 0 Then
        GetBitFromByte = 1
    Else
        GetBitFromByte = 0
    End If
End Function
代码语言:javascript
复制
'从Byte数组中取某一位的Bit
Function GetBit(b() As Byte, ZeroBaseIndex As Long) As Long
    '数组b中,开始的下标
    Dim bindex As Long
    bindex = ZeroBaseIndex \ 8

    GetBit = VBA.CLng(b(bindex)) And (2 ^ (ZeroBaseIndex Mod 8))
    If GetBit > 0 Then
        GetBit = 1
    Else
        GetBit = 0
    End If
End Function
代码语言:javascript
复制
'从Byte数组中取多位bit
' 0000 0000     0000 0000
' 7654 3210     fedc ba98
Function GetBits(b() As Byte, IndexFromZeroBase As Long, iBits As Long) As Long
    Dim i As Long
    Dim tmp As Long

    For i = 0 To iBits - 1
        tmp = GetBit(b, IndexFromZeroBase + i)
        tmp = BitMoveLeft(tmp, i)
        GetBits = GetBits Or tmp
    Next
End Function

'左移
Function BitMoveLeft(ByRef l As Long, num As Long) As Long
    Dim i As Long
    For i = 1 To num
        '会溢出 0x7FFF FFFF
        '判断第31位是否=1
        '不管等不等于1都把第31为置换为0,负数待处理
        l = l And &H3FFFFFFF
        l = l * 2
    Next

    BitMoveLeft = l
End Function

'右移
Function BitMoveRight(ByRef l As Long, num As Long) As Long
    Dim i As Long
    For i = 1 To num
        l = l \ 2
    Next

    BitMoveRight = l
End Function
代码语言:javascript
复制
'从Byte数组中取多位bit
'取出后的bit存储顺序倒置
Function GetBitsRev(b() As Byte, IndexFromZeroBase As Long, iBits As Long) As Long
    Dim i As Long
    Dim tmp As Long

    For i = 0 To iBits - 1
        tmp = GetBit(b, IndexFromZeroBase + i)
        tmp = BitMoveLeft(tmp, iBits - i - 1)
        GetBitsRev = GetBitsRev Or tmp
    Next
End Function
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-07-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 VBA 学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档