Go to Google Groups Home    microsoft.public.vb.general.discussion
How to get the file names of in a zip file

Mike D Sutton <mike.sut...@btclick.com>

>   Could someone advice me on how i could
> get the file names in a zip file.

You'll either need to use a third party .zip library, or parse the .zip
central directory structure.  The format isn't _too_ tricky to parse,
(Assuming you're not dealing with multiple spanned volumes, but even so,
they're not really that much worse) since even when the file is encrypted,
the file header (Including file names) data is stored unencrypted.
A real rough overview of how to read a .ZIP file would be, enter a Do loop
and read 4 bytes from the file, these 4 byte should be a zip signature but
you're only interested in one type which comes at the start of the file, so
check for 0x4034B50.  If the signature matches then you're looking at a
local file header structure which is declared as:

'***
Private Type typZipLocalFileHead ' 30 bytes
    zlfhSignature As Long ' 0x04034B50
    zlfhVersion As Integer
    zlfhBitFlag As Integer
    zlfhCompression As Integer
    zlfhModFileTime As Integer
    zlfhModFileData As Integer
    zlfhCRC As Long
    zlfhCompressedSize As Long
    zlfhUncompressedSize As Long
    zlfhFileNameLength As Integer
    zlfhExtraFieldLength As Integer
End Type
'***

Seek back 4 bytes and read in the entire structure in one shot, or read in
the rest of the structure's fields individually.  Now check the
zlfhFileNameLength field for a positive integer, if so then create a string
of that length and read it in from the file - That's the first filename.
You can also get compression ratio and other information about the file from
the structure depending on what you want to do with it.
Check the zlfhExtraFieldLength field for a positive integer, and if found
skip over that data
Finally, check the 3'rd bit of the zlfhBitFlag member (zlfhBitFlag And &H4)
and if present skip the next 12 bytes (Just a CRC and file sizes again.)
Keep going until you hit a different zip chunk signature and you should have
all your files, here's a quick example of the finished routine:

'***
Private Sub Form_Load()
    SET THE ZIP PATH HERE THEN KILL THIS LINE
    Const FileName As String = "X:\Path\File.zip"
    Debug.Print "Found " & TestZip(FileName) & " files in zip"
End Sub

Private Function TestZip(ByRef inFile As String) As Long
    Dim FileName As String
    Dim ReadHead As typZipLocalFileHead
    Dim FNum As Integer
    Dim FileString As String
    Dim SeekSize As Long

    Const ZipLocalFileHeadSig As Long = &H4034B50

    ' Make sure file exists
    If (Not FileExist(inFile)) Then Exit Function

    ' Get a free file handle and open the file
    FNum = FreeFile()
    Open inFile For Binary Access Read Lock Write As #FNum
        Do ' Read a chunk signature
            Get #FNum, , ReadHead.zlfhSignature

            ' Check for a local file header signatrue
            If (ReadHead.zlfhSignature = ZipLocalFileHeadSig) Then
                ' Ok, read the full structure
                Seek #FNum, Seek(FNum) - 4
                Get #FNum, , ReadHead

                With ReadHead
                    ' Get the file name
                    If (.zlfhFileNameLength) Then
                        FileString = Space(.zlfhFileNameLength)
                        Get #FNum, , FileString
                        Debug.Print "Got file: """ & FileString & """";
                    Else ' No filename?
                        Debug.Print "Got file: [No name]";
                    End If

                    ' Print the compression percentage
                    Debug.Print " -- " & Format(1 - (.zlfhCompressedSize / _
                        .zlfhUncompressedSize), "0.0%")

                    ' Work out how much extra data to skip over
                    SeekSize = .zlfhCompressedSize
                    If (.zlfhExtraFieldLength) Then _
                        SeekSize = SeekSize + .zlfhExtraFieldLength
                    If (.zlfhBitFlag And &H4) Then _
                        SeekSize = SeekSize + 12

                    ' Seek to next record
                    Seek #FNum, Seek(FNum) + SeekSize
                End With

                ' Increment file count
                TestZip = TestZip + 1
            Else
                Exit Do
            End If
        Loop
    Close #FNum
End Function

Private Function FileExist(ByVal inFile As String) As Boolean
    On Error Resume Next
    FileExist = FileLen(inFile) + 1
End Function
'***

Hope this helps,

    Mike

 - Microsoft Visual Basic MVP -
E-Mail: ED...@mvps.org
WWW: Http://www.mvps.org/EDais/