It is currently Mon Oct 14, 2019 5:24 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: Simple ZIP File Routines
PostPosted: Wed Jun 12, 2019 4:22 pm 
Offline
Enthusiast
Enthusiast

Joined: Fri Apr 25, 2003 11:08 pm
Posts: 440
Edit 2019-06-17: Updated code

I don't know if this is already available, but I wrote these simple routines to manipulate ZIP files:
    ZIP_IsZIP(): check if specified file is a ZIP file
    ZIP_FileCount(): count the number of files in ZIP file
    ZIP_FileList(): get a list of filenames/sizes in ZIP file
    ZIP_ExtractFiles(): extract files in ZIP file to folder
    ZIP_ExtractFile(): extract specified file in ZIP to folder

Feel free to use it if you find it useful!

Code:
UseZipPacker()

#ZIP_USEPATHS = #True
#ZIP_ROOTONLY = #False

Structure _ZIPFile
  Filename.S
  Size.l
EndStructure

Prototype.l ZIP_Callback(Filename.S)

;- append trailing backslash to path (if needed)
Procedure.S TrailingBackslash(Path.S)
  If Path
    If Right(Path, 1) = "\"
      ProcedureReturn Path
    Else
      ProcedureReturn Path + "\"
    EndIf
  EndIf
EndProcedure

;- check if specified file is ZIP
Procedure.l ZIP_IsZIP(ZIPFile.S)
  hPack.l = OpenPack(#PB_Any, ZIPFile, #PB_PackerPlugin_Zip)
  If hPack
    IsZIP.l = #True
    ClosePack(hPack)
  EndIf
 
  ProcedureReturn IsZIP
EndProcedure

;- get count of files in specified ZIP file
Procedure.l ZIP_FileCount(ZIPFile.S)
  hPack.l = OpenPack(#PB_Any, ZIPFile, #PB_PackerPlugin_Zip)
  If hPack
    If ExaminePack(hPack)
      While NextPackEntry(hPack)
        If PackEntryType(hPack) = #PB_Packer_File
          FileCount.l + 1
        EndIf
      Wend
    EndIf
    ClosePack(hPack)
    ProcedureReturn FileCount
  Else
    ; indicate open error
    ProcedureReturn -1
  EndIf
EndProcedure

;- get list of files/sizes in specified ZIP file
Procedure.l ZIP_FileList(ZIPFile.S, List ZIPFiles._ZIPFile())
  ClearList(ZIPFiles())
 
  hPack.l = OpenPack(#PB_Any, ZIPFile, #PB_PackerPlugin_Zip)
  If hPack
    If ExaminePack(hPack)
      While NextPackEntry(hPack)
        If PackEntryType(hPack) = #PB_Packer_File
          AddElement(ZIPFiles())
          With ZIPFiles()
            \Filename = PackEntryName(hPack)
            \Size = PackEntrySize(hPack)
          EndWith
        EndIf
      Wend
    EndIf
    ClosePack(hPack)
    ProcedureReturn ListSize(ZIPFiles())
  Else
    ; indicate open error
    ProcedureReturn -1
  EndIf
EndProcedure

;- extract all files in specified ZIP file to specified folder
;- NB: can now specify 'use paths' or 'root only'
Procedure.l ZIP_ExtractFiles(ZIPFile.S, Folder.S, Paths.l = #ZIP_ROOTONLY, Callback.ZIP_Callback = 0)
  hPack.l = OpenPack(#PB_Any, ZIPFile, #PB_PackerPlugin_Zip)
  If hPack
    FolderTB.S = TrailingBackslash(Folder)
    If ExaminePack(hPack)
      While NextPackEntry(hPack)
        Select PackEntryType(hPack)
          Case #PB_Packer_File
            Filename.S = PackEntryName(hPack)
            If Callback
              Callback(Filename)
            EndIf
            If UncompressPackFile(hPack, FolderTB + Filename) >= 0
              Count.l + 1
            EndIf
          Case #PB_Packer_Directory
            If Paths = #ZIP_USEPATHS
              ; create subfolder
              CreateDirectory(FolderTB + PackEntryName(hPack))
            EndIf
        EndSelect
      Wend
    EndIf
    ClosePack(hPack)
    ProcedureReturn Count
  Else
    ; indicate open error
    ProcedureReturn -1
  EndIf
EndProcedure

;- extract specified file in specified ZIP file to specified folder
;- NB: this only works with files in the root folder of ZIP file
Procedure.l ZIP_ExtractFile(ZIPFile.S, Folder.S, FileInZIP.S)
  hPack.l = OpenPack(#PB_Any, ZIPFile, #PB_PackerPlugin_Zip)
  If hPack
    FolderTB.S = TrailingBackslash(Folder)
    FileSize.l = UncompressPackFile(hPack, FolderTB + FileInZIP, FileInZIP)
    ClosePack(hPack)
    ; return uncompressed size of extracted file, -1 if error
    ProcedureReturn FileSize
  Else
    ; indicate open error
    ProcedureReturn -1
  EndIf
EndProcedure

;- example program
NewList FilesInZIP._ZIPFile()

; file extract callback
Procedure MyZIPCallback(Filename.S)
  Debug Filename
EndProcedure

ZIPFile.S = OpenFileRequester("Select ZIP File", "C:\", "ZIP Files (*.zip)|*.zip|All Files (*.*)|*.*", 0)
If ZIPFile
  ; check if zip file
  If ZIP_IsZIP(ZIPFile)
    ; count files in ZIP
    MessageRequester("ZIP File: " + ZIPFile, Str(ZIP_FileCount(ZIPFile)) + " files")
    ; get list of filenames/sizes in ZIP
    FileCount.l = ZIP_FileList(ZIPFile, FilesInZIP())
    ForEach FilesInZIP()
      With FilesInZIP()
        message.S + \Filename + "  " + Str(\Size) + #LF$
      EndWith
    Next
    If MessageRequester("ZIP File: " + ZIPFile + " - Extract?", Str(FileCount) + " files" + #LF$ + #LF$ + message, #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
      ; extract files to specified folder
      Folder.S = PathRequester("Select Output Folder", "C:\")
      If Folder
        ; extract one file
        ; extract files with/without callback
        ; NB: can now specify 'use paths' or 'root only'
        FileCount.l = ZIP_ExtractFiles(ZIPFile, Folder, #ZIP_USEPATHS, @MyZIPCallback())
        ;FileCount.l = ZIP_ExtractFiles(ZIPFile, Folder)
        MessageRequester("ZIP File: " + ZIPFile, Str(FileCount) + " files extracted")
      EndIf
    EndIf
  Else
    MessageRequester("ZIP File: " + ZIPFile, "File is not a ZIP file!", #MB_ICONERROR)
  EndIf
EndIf


Last edited by ebs on Mon Jun 17, 2019 2:11 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Simple ZIP File Routines
PostPosted: Fri Jun 14, 2019 5:20 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sat Aug 09, 2003 3:13 am
Posts: 775
Location: 90-61-92 // EU or ASIA
ebs wrote:
I don't know if this is already available, but I wrote these simple routines to manipulate ZIP files:
    ZIP_IsZIP(): check if specified file is a ZIP file
    ZIP_FileCount(): count the number of files in ZIP file
    ZIP_FileList(): get a list of filenames/sizes in ZIP file
    ZIP_ExtractFiles(): extract files in ZIP file to folder

Feel free to use it if you find it useful!

Code:
UseZipPacker()

Structure _ZIPFile
  Filename.S
  Size.l
EndStructure

Prototype.i ZIP_Callback(Filename.S)

;- append trailing backslash to path (if needed)
Procedure.S TrailingBackslash(Path.S)
  If Path
    If Right(Path, 1) = "\"
      ProcedureReturn Path
    Else
      ProcedureReturn Path + "\"
    EndIf
  EndIf
EndProcedure

;- check signature to see if specified file is ZIP
Procedure.l ZIP_IsZIP(ZIPFile.S)
  hPack.l = OpenPack(#PB_Any, ZIPFile, #PB_PackerPlugin_Zip)
  If hPack
    IsZIP.l = #True
    ClosePack(hPack)
  EndIf
 
  ProcedureReturn IsZIP
EndProcedure

;- get count of files in specified ZIP file
Procedure.l ZIP_FileCount(ZIPFile.S)
  hPack.l = OpenPack(#PB_Any, ZIPFile, #PB_PackerPlugin_Zip)
  If hPack
    While NextPackEntry(hPack)
      If PackEntryType(hPack) = #PB_Packer_File
        FileCount.l + 1
      EndIf
    Wend
    ClosePack(hPack)
    ProcedureReturn FileCount
  Else
    ; indicate open error
    ProcedureReturn -1
  EndIf
EndProcedure
;- get list of files/sizes in specified ZIP file
Procedure.l ZIP_FileList(ZIPFile.S, List ZIPFiles._ZIPFile())
  ClearList(ZIPFiles())
 
  hPack.l = OpenPack(#PB_Any, ZIPFile, #PB_PackerPlugin_Zip)
  If hPack
    While NextPackEntry(hPack)
      If PackEntryType(hPack) = #PB_Packer_File
        AddElement(ZIPFiles())
        With ZIPFiles()
          \Filename = PackEntryName(hPack)
          \Size = PackEntrySize(hPack)
        EndWith
      EndIf
    Wend
    ClosePack(hPack)
    ProcedureReturn ListSize(ZIPFiles())
  Else
    ; indicate open error
    ProcedureReturn -1
  EndIf
EndProcedure
;- extract files in specified ZIP file to specified folder
Procedure.l ZIP_ExtractFiles(ZIPFile.S, Folder.S, Callback.ZIP_Callback = 0)
  hPack.l = OpenPack(#PB_Any, ZIPFile, #PB_PackerPlugin_Zip)
  If hPack
    FolderTB.S = TrailingBackslash(Folder)
    While NextPackEntry(hPack)
      If PackEntryType(hPack) = #PB_Packer_File
        Filename.S = PackEntryName(hPack)
        If Callback
          Callback(Filename)
        EndIf
        UncompressPackFile(hPack, FolderTB + Filename)
        Count.l + 1
      EndIf
    Wend
    ClosePack(hPack)
    ProcedureReturn Count
  Else
    ; indicate open error
    ProcedureReturn -1
  EndIf
EndProcedure

NewList FilesInZIP._ZIPFile()

; file extract callback
Procedure MyZIPCallback(Filename.S)
  Debug Filename
EndProcedure

ZIPFile.S = OpenFileRequester("Select ZIP File", "C:\", "ZIP Files (*.zip)|*.zip|All Files (*.*)|*.*", 0)
If ZIPFile
  ; check if zip file
  If ZIP_IsZIP(ZIPFile)
    ; count files in ZIP
    MessageRequester("ZIP File: " + ZIPFile, Str(ZIP_FileCount(ZIPFile)) + " files")
    ; get list of filenames/sizes in ZIP
    FileCount.l = ZIP_FileList(ZIPFile, FilesInZIP())
    ForEach FilesInZIP()
      With FilesInZIP()
        message.S + \Filename + "  " + Str(\Size) + #LF$
      EndWith
    Next
    If MessageRequester("ZIP File: " + ZIPFile + " - Extract?", Str(FileCount) + " files" + #LF$ + #LF$ + message, #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
      ; extract files to specified folder
      Folder.S = PathRequester("Select Output Folder", "C:\")
      If Folder
        ; extract files with/without callback
        FileCount.l = ZIP_ExtractFiles(ZIPFile, Folder, @MyZIPCallback())
        ;FileCount.l = ZIP_ExtractFiles(ZIPFile, Folder)
        MessageRequester("ZIP File: " + ZIPFile, Str(FileCount) + " files extracted")
      EndIf
    EndIf
  Else
    MessageRequester("ZIP File: " + ZIPFile, "File is not a ZIP file!", #MB_ICONERROR)
  EndIf
EndIf


Great stuff, thx.

Does ZIP_ExtractFiles support e, x same as 7z command line?
Quote:
e : Extract files from archive (without using directory names)
x : eXtract files with full paths


Top
 Profile  
Reply with quote  
 Post subject: Re: Simple ZIP File Routines
PostPosted: Fri Jun 14, 2019 1:06 pm 
Offline
Enthusiast
Enthusiast

Joined: Fri Apr 25, 2003 11:08 pm
Posts: 440
sec wrote:
Does ZIP_ExtractFiles support e, x same as 7z command line?
Quote:
e : Extract files from archive (without using directory names)
x : eXtract files with full paths

It's pretty simple code, so it doesn't deal with paths in the ZIP file.
It just extracts the files in the "root directory" of the ZIP file.

The "ZIP_FileList()" will include files in a folder, but they aren't extracted.
That seems like a straightforward thing to add; I'll take a look.

In the meantime, here's a procedure to extract a specified file, not all files:
Code:
;- extract specified file in specified ZIP file to specified folder
Procedure.l ZIP_ExtractFile(ZIPFile.S, Folder.S, FileInZIP.S)
  hPack.l = OpenPack(#PB_Any, ZIPFile, #PB_PackerPlugin_Zip)
  If hPack
    FolderTB.S = TrailingBackslash(Folder)
    FileSize.l = UncompressPackFile(hPack, FolderTB + FileInZIP, FileInZIP)
    ClosePack(hPack)
    ; return uncompressed size of extracted file, -1 if error
    ProcedureReturn FileSize
  Else
    ; indicate open error
    ProcedureReturn -1
  EndIf
EndProcedure


Top
 Profile  
Reply with quote  
 Post subject: Re: Simple ZIP File Routines
PostPosted: Fri Jun 14, 2019 2:00 pm 
Offline
Enthusiast
Enthusiast

Joined: Fri Apr 25, 2003 11:08 pm
Posts: 440
Here's updated code that supports extracting files from paths or from the root only.

While I was revising the code, I noticed that I had forgotten to use the "ExaminePack()" procedure.
The funny thing is that the code works with or without it. I added it in this version to be correct.
Code:
UseZipPacker()

#ZIP_USEPATHS = #True
#ZIP_ROOTONLY = #False

Structure _ZIPFile
  Filename.S
  Size.l
EndStructure

Prototype.l ZIP_Callback(Filename.S)

;- append trailing backslash to path (if needed)
Procedure.S TrailingBackslash(Path.S)
  If Path
    If Right(Path, 1) = "\"
      ProcedureReturn Path
    Else
      ProcedureReturn Path + "\"
    EndIf
  EndIf
EndProcedure

;- check if specified file is ZIP
Procedure.l ZIP_IsZIP(ZIPFile.S)
  hPack.l = OpenPack(#PB_Any, ZIPFile, #PB_PackerPlugin_Zip)
  If hPack
    IsZIP.l = #True
    ClosePack(hPack)
  EndIf
 
  ProcedureReturn IsZIP
EndProcedure

;- get count of files in specified ZIP file
Procedure.l ZIP_FileCount(ZIPFile.S)
  hPack.l = OpenPack(#PB_Any, ZIPFile, #PB_PackerPlugin_Zip)
  If hPack
    If ExaminePack(hPack)
      While NextPackEntry(hPack)
        If PackEntryType(hPack) = #PB_Packer_File
          FileCount.l + 1
        EndIf
      Wend
    EndIf
    ClosePack(hPack)
    ProcedureReturn FileCount
  Else
    ; indicate open error
    ProcedureReturn -1
  EndIf
EndProcedure

;- get list of files/sizes in specified ZIP file
Procedure.l ZIP_FileList(ZIPFile.S, List ZIPFiles._ZIPFile())
  ClearList(ZIPFiles())
 
  hPack.l = OpenPack(#PB_Any, ZIPFile, #PB_PackerPlugin_Zip)
  If hPack
    If ExaminePack(hPack)
      While NextPackEntry(hPack)
        If PackEntryType(hPack) = #PB_Packer_File
          AddElement(ZIPFiles())
          With ZIPFiles()
            \Filename = PackEntryName(hPack)
            \Size = PackEntrySize(hPack)
          EndWith
        EndIf
      Wend
    EndIf
    ClosePack(hPack)
    ProcedureReturn ListSize(ZIPFiles())
  Else
    ; indicate open error
    ProcedureReturn -1
  EndIf
EndProcedure

;- extract all files in specified ZIP file to specified folder
;- NB: can now specify 'use paths' or 'root only'
Procedure.l ZIP_ExtractFiles(ZIPFile.S, Folder.S, Paths.l = #ZIP_ROOTONLY, Callback.ZIP_Callback = 0)
  hPack.l = OpenPack(#PB_Any, ZIPFile, #PB_PackerPlugin_Zip)
  If hPack
    FolderTB.S = TrailingBackslash(Folder)
    If ExaminePack(hPack)
      While NextPackEntry(hPack)
        Select PackEntryType(hPack)
          Case #PB_Packer_File
            Filename.S = PackEntryName(hPack)
            If Callback
              Callback(Filename)
            EndIf
            If UncompressPackFile(hPack, FolderTB + Filename) >= 0
              Count.l + 1
            EndIf
          Case #PB_Packer_Directory
            If Paths = #ZIP_USEPATHS
              ; create subfolder
              CreateDirectory(FolderTB + PackEntryName(hPack))
            EndIf
        EndSelect
      Wend
    EndIf
    ClosePack(hPack)
    ProcedureReturn Count
  Else
    ; indicate open error
    ProcedureReturn -1
  EndIf
EndProcedure

;- extract specified file in specified ZIP file to specified folder
;- NB: this only works with files in the root folder of ZIP file
Procedure.l ZIP_ExtractFile(ZIPFile.S, Folder.S, FileInZIP.S)
  hPack.l = OpenPack(#PB_Any, ZIPFile, #PB_PackerPlugin_Zip)
  If hPack
    FolderTB.S = TrailingBackslash(Folder)
    FileSize.l = UncompressPackFile(hPack, FolderTB + FileInZIP, FileInZIP)
    ClosePack(hPack)
    ; return uncompressed size of extracted file, -1 if error
    ProcedureReturn FileSize
  Else
    ; indicate open error
    ProcedureReturn -1
  EndIf
EndProcedure

;- example program
NewList FilesInZIP._ZIPFile()

; file extract callback
Procedure MyZIPCallback(Filename.S)
  Debug Filename
EndProcedure

ZIPFile.S = OpenFileRequester("Select ZIP File", "C:\", "ZIP Files (*.zip)|*.zip|All Files (*.*)|*.*", 0)
If ZIPFile
  ; check if zip file
  If ZIP_IsZIP(ZIPFile)
    ; count files in ZIP
    MessageRequester("ZIP File: " + ZIPFile, Str(ZIP_FileCount(ZIPFile)) + " files")
    ; get list of filenames/sizes in ZIP
    FileCount.l = ZIP_FileList(ZIPFile, FilesInZIP())
    ForEach FilesInZIP()
      With FilesInZIP()
        message.S + \Filename + "  " + Str(\Size) + #LF$
      EndWith
    Next
    If MessageRequester("ZIP File: " + ZIPFile + " - Extract?", Str(FileCount) + " files" + #LF$ + #LF$ + message, #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
      ; extract files to specified folder
      Folder.S = PathRequester("Select Output Folder", "C:\")
      If Folder
        ; extract one file
        ; extract files with/without callback
        ; NB: can now specify 'use paths' or 'root only'
        FileCount.l = ZIP_ExtractFiles(ZIPFile, Folder, #ZIP_USEPATHS, @MyZIPCallback())
        ;FileCount.l = ZIP_ExtractFiles(ZIPFile, Folder)
        MessageRequester("ZIP File: " + ZIPFile, Str(FileCount) + " files extracted")
      EndIf
    EndIf
  Else
    MessageRequester("ZIP File: " + ZIPFile, "File is not a ZIP file!", #MB_ICONERROR)
  EndIf
EndIf


Top
 Profile  
Reply with quote  
 Post subject: Re: Simple ZIP File Routines
PostPosted: Sat Jun 15, 2019 1:47 am 
Offline
Enthusiast
Enthusiast

Joined: Thu Apr 18, 2019 8:17 am
Posts: 325
Thanks for the code, ebs. However, it won't unzip password-protected archives. Is that planned?

Also, to save us scrolling through this thread to find the latest version, I suggest you always edit the first post with the latest code. That's the norm for this type of thing. ;)


Top
 Profile  
Reply with quote  
 Post subject: Re: Simple ZIP File Routines
PostPosted: Mon Jun 17, 2019 2:17 pm 
Offline
Enthusiast
Enthusiast

Joined: Fri Apr 25, 2003 11:08 pm
Posts: 440
First post updated with new code.

Regarding ZIP password - I wrote these routines for a work project where I had no need to work with password-protected ZIP files.
Also, as far as I know, PB has no way to deal with ZIP passwords.


Top
 Profile  
Reply with quote  
 Post subject: Re: Simple ZIP File Routines
PostPosted: Tue Jun 18, 2019 1:05 am 
Offline
Enthusiast
Enthusiast

Joined: Thu Apr 18, 2019 8:17 am
Posts: 325
Thanks for editing the first post to make it easier to get the latest code. :)

I was hoping you'd know a way to decode passworded zip files yourself with some code. I hope Fred can add encryption/decryption one day.


Top
 Profile  
Reply with quote  
 Post subject: Re: Simple ZIP File Routines
PostPosted: Tue Jun 18, 2019 5:27 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sat Aug 09, 2003 3:13 am
Posts: 775
Location: 90-61-92 // EU or ASIA
BarryG wrote:
Thanks for editing the first post to make it easier to get the latest code. :)

I was hoping you'd know a way to decode passworded zip files yourself with some code. I hope Fred can add encryption/decryption one day.

You can run
Quote:
7za.exe -p{Password} : set Password
with RunProgram()


Top
 Profile  
Reply with quote  
 Post subject: Re: Simple ZIP File Routines
PostPosted: Tue Jun 18, 2019 6:11 am 
Offline
Enthusiast
Enthusiast

Joined: Thu Apr 18, 2019 8:17 am
Posts: 325
Good idea, sec!


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: kvitaliy and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye