Page 2 of 2
Re: Problem with code snippet
Posted: 02 Dec 2019 16:34
by ColeValleyGirl
If you could add zip that would be great.
Does
Code: Select all
local zfile = assert(zip.open(zipPath.."\\"..zipFilename),"Failed to open zip file "..zipPath.."\\"..zipFilename) --open the zip file for processing
address the error handling requirement?
I'm not a fan of offline help because I shall eventually fall off the twig and want to leave people with something they can continue to use when my hosting arrangements go down the river... and I want to use help html which the FHUG wiki can't support.
Once tested, I shall post it as a separate code snippet (as it has different restrictions and functionality to the other set).
Re: Problem with code snippet
Posted: 02 Dec 2019 17:09
by tatewise
Have added the
zip download.
I was thinking more along the lines of:
Code: Select all
if zfile then
--get the identity of any subdirectories and create them in destinationPath
for loops ...
zfile:close()
else
fhMessageBox( err )
end
BTW: I have spotted that none of those
"\\".. are needed. Just use
zipPath..zipFilename
Re: Problem with code snippet
Posted: 02 Dec 2019 17:18
by ColeValleyGirl
Any reason you prefer that approach? I would expect to do the error handling before the snippet is invoked (customised to the calling plugin), so the assert statement is just belt and braces -- i.e. not call ExtractZip unless I knew the zip file existed.
I get errors without the \\ -- which specific ones do you think are unnecessary?
Re: Problem with code snippet
Posted: 02 Dec 2019 17:52
by tatewise
Yes, my script is inside the function ExtractZip snippet the same as your assert(...).
I prefer the more user friendly style of fhMessageBox instead of the scarier Plugin Error message.
Also it uses the actual error message returned by zip.open that may be more explicit than Failed to open zip file.
But as you say, it should only be a backstop, so I have no strong preference.
The "\\".. depend on exactly what is provided in zipPath and destinationPath.
I used different paths that had trailing \\ but I see now your original script does not.
So if the "\\".. are omitted you get an error if the \\ are needed.
Or if the "\\".. are included when not needed you get double \ in the path error message.
The 'perfect' solution is to add zipPath = zipPath:gsub("\\$","") and similar for destinationPath and retain the "\\"..
Re: Problem with code snippet
Posted: 03 Dec 2019 14:25
by tatewise
I have looked at the
ExtractZip snippet again and below is my proposed script.
It adds the
gsub("\\$","") to strip optional trailing backslashes from paths.
It has only one iteration loop
for file in zfile:files() do that both creates new paths and copies files.
Was there a reason why your original needed to have two loops?
Code: Select all
function ExtractZip(zipPath, zipFilename, destinationPath)
zipPath = zipPath:gsub("\\$","")
destinationPath = destinationPath:gsub("\\$","")
local zfile = assert(zip.open(zipPath.."\\"..zipFilename),"Failed to open zip file "..zipPath.."\\"..zipFilename) --open the zip file for processing
local function CopyFile(file)
local currFile, err = zfile:open(file.filename) --open a file within the zipfile
local currFileContents = currFile:read("*a") -- read entire contents of current file
local hBinaryOutput = io.open(destinationPath .."\\".. file.filename, "wb") --open an outputfile
-- write current file inside zip to a file outside zip
if hBinaryOutput then
hBinaryOutput:write(currFileContents) --write the new file as a copy of the file within the zipfile
hBinaryOutput:close() --close the new file
end
currFile:close() --close the file within the zipfile
end
-- iterate through each file inside the zip file
for file in zfile:files() do
local newdir = path.dirname(file.filename)
if not path.exists(destinationPath.."\\"..newdir) then dir.makepath(destinationPath.."\\"..newdir) end
if path.basename(file.filename) ~= "" then CopyFile(file) end
end
zfile:close()
end
Re: Problem with code snippet
Posted: 03 Dec 2019 14:39
by ColeValleyGirl
Re two loops, it was easier for testing -- one is fine.
One thing I suspect (and haven't had a chance to verify): the code is losing the case of the unzipped files/directories.
Edited: Yes, it's converting names to lower case.
Re: Problem with code snippet
Posted: 03 Dec 2019 15:11
by tatewise
Solution is to use lfs.mkdir in place of dir.makepath but it needs to be presented with one nested path at a time.
The copied files do retain their case.
Re: Problem with code snippet
Posted: 03 Dec 2019 15:24
by ColeValleyGirl
I can live with it at present as the case for the directory doesn't matter, but I will make a note to revisit when I have some time.
Re: Problem with code snippet
Posted: 03 Dec 2019 15:44
by tatewise
This will do it:
Code: Select all
-- iterate through each file inside the zip file
for file in zfile:files() do
local newdir = path.dirname(file.filename)
if not path.exists(destinationPath.."\\"..newdir) then
local destPath = destinationPath
for nextdir in newdir:gmatch("[^/]+") do
destPath = destPath.."\\"..nextdir
lfs.mkdir(destPath)
end
end
if path.basename(file.filename) ~= "" then CopyFile(file) end
end