Zip File Create & Extract (code snippet)

Description

Creates a Compressed (zipped) Folder from the contents of any folder, or extracts a Compressed (zipped) Folder into any folder.

Requires: luacom

For more information on options in the shell.application object see: Shell Object

An alternative version of the extractZip function uses the LuaZip module.

Requires: zip & lfs

Primary Code

ZipFile.fh_lua
require "luacom"
 
function buildZip(zipFile,folder)
    -- Create Empty Zip File
    local strZipHeader = 'PK'..string.char(5,6)..string.rep(string.char(0), 18)
    zip = assert(io.open(zipFile, 'w'))
    zip:write(strZipHeader)
    zip:close()
    --  Create com object to work with Files and Folders
    local shell = luacom.CreateObject("Shell.Application")
    local source = shell:NameSpace(folder)  -- Get the source folder
    local items = source:items()
    local dest = shell:NameSpace(zipFile)   -- Get the destination Zip file
    dest:CopyHere(items)    -- Copy the Source folder to the Zip file 
    repeat                  -- Check that copy to Zip completed
        local count = dest:items().count
        if count == items.count then return true end
        fhSleep(1000,500)
    until count == dest:items().count
    return false
end -- function buildZip
 
function extractZip(zipFile,folder)
    --  Create com object to work with Files and Folders
    local shell = luacom.CreateObject("Shell.Application")
    local source = shell:NameSpace(zipFile)  -- Get the zip file
    local items = source:items()
    local dest = shell:NameSpace(folder)   -- Get the destination folder file
    local files = dest:items().count + items.count -- Count of top level items already in folder plus those in zip file
    dest:CopyHere(items)    -- Copy the Zip to the Folder
    repeat                  -- Check that copy of Zip completed
        local count = dest:items().count
        if count == files then return true end
        fhSleep(1000,500)
    until count == dest:items().count
    return false
end -- function extractZip

items.count is the number of top level files & folders within the source folder or Zip file.
dest:items().count is number of top level files & folders in the destination Zip file or folder.

Usage

local strfolder = 'd:\\temp\\AVG\\'
local strzipfile = 'd:\\temp\\test2.zip'
-- Add Folder contents to Zip
if not buildZip(strzipfile,strfolder) then fhMessageBox("Create Zip File Failed.") end
-- Extract zip contents to folder
if not extractZip(strzipfile,strfolder) then fhMessageBox("Extract Zip File Failed.") end

Alternative Code

ExtractZip.fh_lua
if not fhloadrequire("zip") then return end
require "lfs"
 
function extractZip(zipFile,folder)
 
    folder = folder:gsub("\\$","")
    local zfile = assert(zip.open(zipFile),"Failed to open zip file "..zipFile)  -- Open zip file
 
    local function CopyFile(filename)
        local currFile,err = zfile:open(filename)  -- Open a file within the zip file
        local currContents = currFile:read("*a")   -- Get contents of current file
        local binaryOutput = io.open(folder.."\\"..filename,"wb")  -- Open output file
        if binaryOutput then
            binaryOutput:write(currContents)  -- Write current file from zip to output file
            binaryOutput:close()
        end
        currFile:close()
    end -- local function CopyFile
 
    for file in zfile:files() do    -- Iterate through each file inside the zip file
        local newdir, newfile = file.filename:match("^(.-)/?([^/]*)$")
        local destPath = folder.."\\"..newdir
        if lfs.attributes(destPath,"mode") ~= "directory" then  -- Make new directory?
            destPath = folder
            for nextdir in newdir:gmatch("[^/]+") do
                destPath = destPath.."\\"..nextdir
                if lfs.attributes(destPath,"mode") ~= "directory" then
                   lfs.mkdir(destPath)   -- Make each new subdirectory
                end
            end
        end
        if #newfile > 0 then CopyFile(file.filename) end  -- Copy new file?
    end
    zfile:close()
end -- function extractZip

Usage

local strfolder = 'd:\\temp\\AVG\\'
local strzipfile = 'd:\\temp\\test2.zip'
-- Extract zip contents to folder
extractZip(strzipfile,strfolder)