Page 1 of 2

Parse zip file without using a library

Posted: Fri Jul 25, 2008 8:54 am
by Rings

Code: Select all

Structure typZipLocalFileHead ; 30 bytes
    zlfhSignature.l; As Long ' 0x04034B50
    zlfhVersion.w; As Integer
    zlfhBitFlag.w; As Integer
    zlfhCompression.w; As Integer
    zlfhModFileTime.w; As Integer
    zlfhModFileData.w; As Integer
    zlfhCRC.l; As Long
    zlfhCompressedSize.l; As Long
    zlfhUncompressedSize.l; As Long
    zlfhFileNameLength.w; As Integer
    zlfhExtraFieldLength.w; As Integer
EndStructure

Procedure ListZipFile(Filename.s)
  ReadHead.typZipLocalFileHead
 FF=ReadFile(#PB_Any,Filename)
 If FF
  again:
  ReadHead\zlfhSignature= ReadLong(ff)
  If ReadHead\zlfhSignature=$4034B50
   ;Debug "valid Zip File!"
   FileSeek(FF,Loc(ff)-4)
   ;Debug Loc(FF)
     
   Laenge = ReadData(FF, @ReadHead, SizeOf(ReadHead))
   ;Debug Loc(FF)
     
   With ReadHead
     ; Get the file name
     If \zlfhFileNameLength<>0  
      FileString.s = Space(\zlfhFileNameLength)
      ;Debug Loc(FF)
      Laenge = ReadData(FF, @FileString, \zlfhFileNameLength)
      ;Debug Loc(FF)
      Debug Filestring
     EndIf
     Debug"  Compressed="  + Str(\zlfhCompressedSize) + " UnCompressed="  + Str(\zlfhUnCompressedSize)
     ;Debug \zlfhExtraFieldLength
     ;Debug \zlfhBitFlag
     
     ; Work out how much extra Data To skip over
     SeekSize = \zlfhCompressedSize
     If \zlfhExtraFieldLength
      SeekSize + \zlfhExtraFieldLength
     EndIf
     If (\zlfhBitFlag & $4) 
      SeekSize  + 12
     EndIf
     
     ;Debug Seeksize
   
   EndWith 
   
   ;Seek To Next record
   Seeksize + Loc(FF)
   ;Debug Seeksize
   FileSeek(FF,Seeksize)
   ; Increment file count
   Filecount + 1
   Goto again 
  
  Else
   Debug "no more entries in ZIP"
  EndIf
  Debug Str(Filecount) + " in ZipFile"
  
  CloseFile(FF)
 EndIf

EndProcedure

FileName.s= "c:\B0712021_Botek_Werk3_HMI.zip"
ListZipFile(FileName) 
changed code to open file readonly

Posted: Fri Jul 25, 2008 10:17 am
by srod
Very nice. :)

It always displays a 'no valid ZIP' right at the end though! Ah, I see why; easily fixed.

Thanks.

Re: Parse zip file without using a library

Posted: Fri Jul 25, 2008 10:44 am
by PB
Thanks for translating this Visual Basic code, but it doesn't seem to work yet?
At least not with any zip files that I tested it with. I get no debug output at all.

Re: Parse zip file without using a library

Posted: Fri Jul 25, 2008 10:53 am
by Rings
PB wrote:Thanks for translating this Visual Basic code, but it doesn't seem to work yet?
At least not with any zip files that I tested it with. I get no debug output at all.
what would you espect from a quick VB port from me ?
:lol:

anyway, can you post the zipfiles that did not work ?
(mine here works okay)

Posted: Fri Jul 25, 2008 11:06 am
by srod
Yes works fine here on zips created by WinZip 8.1 and IZarc.

Posted: Fri Jul 25, 2008 12:05 pm
by PB
> can you post the zipfiles that did not work ?

Here's one: http://www.sendspace.com/file/fh0ewy

Posted: Fri Jul 25, 2008 1:04 pm
by Rings
debugger wrote :
NViewLib/
Compressed=0 UnCompressed=0
NViewLib/NViewLib.dll
Compressed=132009 UnCompressed=265216
NViewLib/NViewLib.rtf
Compressed=4540 UnCompressed=18723
no valid ZIP
3 in ZipFile
seems okay, one directory and 2 files

Posted: Fri Jul 25, 2008 1:34 pm
by PB
Ah, I worked it out. If the zip file is marked as ReadOnly, it won't work. Try it. :)

Posted: Fri Jul 25, 2008 1:37 pm
by milan1612
PB wrote:Ah, I worked it out. If the zip file is marked as ReadOnly, it won't work. Try it. :)
That's because Rings used OpenFile instead of ReadFile... :wink:

Posted: Fri Jul 25, 2008 1:46 pm
by PB
> That's because Rings used OpenFile instead of ReadFile

Eureka! :) I changed it to ReadFile and it works perfectly now.
(Well, except that he also uses Goto too! :twisted: ).

But seriously: thank you, Rings, for porting the Visual Basic code.

Posted: Fri Jul 25, 2008 2:00 pm
by bobobo
Everybody DO use GOTO .. (if loops are used)
look at Your pb's ASM output and search for JMP.

so what ?

Posted: Fri Jul 25, 2008 2:01 pm
by Rings
PB wrote:(Well, except that he also uses Goto too! :twisted: ).
what wrong with the native equivalent of the
JMP (CPU's instruction set) Command :wink:

Posted: Fri Jul 25, 2008 2:11 pm
by PB
The Goto thing was a joke. :) But since there was a reaction, how could the
code be modified NOT to use it, since so many people say that any code can
be written without Goto if they really wanted to. To those people: show me.

Posted: Fri Jul 25, 2008 2:22 pm
by srod

Code: Select all

Structure typZipLocalFileHead ; 30 bytes 
    zlfhSignature.l; As Long ' 0x04034B50 
    zlfhVersion.w; As Integer 
    zlfhBitFlag.w; As Integer 
    zlfhCompression.w; As Integer 
    zlfhModFileTime.w; As Integer 
    zlfhModFileData.w; As Integer 
    zlfhCRC.l; As Long 
    zlfhCompressedSize.l; As Long 
    zlfhUncompressedSize.l; As Long 
    zlfhFileNameLength.w; As Integer 
    zlfhExtraFieldLength.w; As Integer 
EndStructure 

Procedure ListZipFile(Filename.s) 
  ReadHead.typZipLocalFileHead 
 FF=ReadFile(#PB_Any,Filename) 
 If FF 
  Repeat
    ReadHead\zlfhSignature= ReadLong(ff) 
    If ReadHead\zlfhSignature=$4034B50 
      ;Debug "valid Zip File!" 
      FileSeek(FF,Loc(ff)-4) 
      ;Debug Loc(FF) 
      
      Laenge = ReadData(FF, @ReadHead, SizeOf(ReadHead)) 
      ;Debug Loc(FF) 
      
      With ReadHead 
        ; Get the file name 
        If \zlfhFileNameLength<>0  
          FileString.s = Space(\zlfhFileNameLength) 
          ;Debug Loc(FF) 
          Laenge = ReadData(FF, @FileString, \zlfhFileNameLength) 
          ;Debug Loc(FF) 
          Debug Filestring 
        EndIf 
        Debug"  Compressed="  + Str(\zlfhCompressedSize) + " UnCompressed="  + Str(\zlfhUnCompressedSize) 
        ;Debug \zlfhExtraFieldLength 
        ;Debug \zlfhBitFlag 
      
        ; Work out how much extra Data To skip over 
        SeekSize = \zlfhCompressedSize 
        If \zlfhExtraFieldLength 
          SeekSize + \zlfhExtraFieldLength 
        EndIf 
        If (\zlfhBitFlag & $4) 
          SeekSize  + 12 
        EndIf 
      
        ;Debug Seeksize 
    
      EndWith 
    
      ;Seek To Next record 
        Seeksize + Loc(FF) 
      ;Debug Seeksize 
      FileSeek(FF,Seeksize) 
      ; Increment file count 
      Filecount + 1 
    Else 
      If fileCount = 0
        Debug "no valid ZIP" 
      EndIf
      quitLoop = 1
    EndIf 
  Until quitLoop
  Debug Str(Filecount) + " in ZipFile" 
  
  CloseFile(FF) 
 EndIf 

EndProcedure 

FileName.s= "arrayClass.zip" 
ListZipFile(FileName) 

Posted: Fri Jul 25, 2008 2:45 pm
by PB
:)