Recent

Author Topic: [SOLVED] Unzipping ONE file from zip archive  (Read 1155 times)

maurobio

  • Full Member
  • ***
  • Posts: 102
[SOLVED] Unzipping ONE file from zip archive
« on: December 04, 2019, 10:25:17 pm »
Dear ALL,

This question may look ridicule, but... how do I extract just one file from a zip archive using TUnzipper?

There are plenty of examples of how to extracting all files from an archive at once, but I could not find a single example of how to extract just one of them.

I know in advance the name of the file to be extracted, anyway it should be helpful to check if it really exists in the archive. Are there a way of doing this without running over all the archive entries?

Thanks!

EDIT: I see now that there is an UnzipFiles procedure in the TUnZipper unit which unzips specified files, but an example of its usage would be very helpful.
« Last Edit: December 04, 2019, 11:00:10 pm by maurobio »
UCSD Pascal / Burroughs 6700 / Master Control Program
Lazarus 1.9.3/2.0.4 - FPC 3.0.4 on GNU/Linux Mint 19 ("Tessa"), Windows XP SP3, Windows 7 Professional, Windows 10 Home

winni

  • Hero Member
  • *****
  • Posts: 590
Re: Unzipping ONE file from zip archive
« Reply #1 on: December 04, 2019, 10:47:47 pm »
Hi

Linux unzip syntax  is just

Code: Bash  [Select]
  1. unzip source.zip  MyDesiredFile

Winni

wp

  • Hero Member
  • *****
  • Posts: 6471
Re: Unzipping ONE file from zip archive
« Reply #2 on: December 04, 2019, 10:56:16 pm »
These are the public methods and properties of the TUnzipper class:
Code: Pascal  [Select]
  1. type
  2.   TUnzipper = class(TObject)
  3.   ...
  4.   Public
  5.     Constructor Create;
  6.     Destructor Destroy;override;
  7.     Procedure UnZipAllFiles; virtual;
  8.     Procedure UnZipFiles(AFileName : String; FileList : TStrings);
  9.     Procedure UnZipFiles(FileList : TStrings);
  10.     Procedure UnZipAllFiles(AFileName : String);
  11.     Procedure Clear;
  12.     Procedure Examine;
  13.   Public
  14.     Property BufferSize : LongWord Read FBufSize Write SetBufSize;
  15.     Property OnOpenInputStream: TCustomInputStreamEvent read FOnOpenInputStream write FOnOpenInputStream;
  16.     Property OnCloseInputStream: TCustomInputStreamEvent read FOnCloseInputStream write FOnCloseInputStream;
  17.     Property OnCreateStream : TOnCustomStreamEvent Read FOnCreateStream Write FOnCreateStream;
  18.     Property OnDoneStream : TOnCustomStreamEvent Read FOnDoneStream Write FOnDoneStream;
  19.     Property OnPercent : Integer Read FOnPercent Write FOnPercent;
  20.     Property OnProgress : TProgressEvent Read FOnProgress Write FOnProgress;
  21.     Property OnStartFile : TOnStartFileEvent Read FOnStartFile Write FOnStartFile;
  22.     Property OnEndFile : TOnEndOfFileEvent Read FOnEndOfFile Write FOnEndOfFile;
  23.     Property FileName : String Read FFileName Write SetFileName;
  24.     Property OutputPath : String Read FOutputPath Write SetOutputPath;
  25.     Property FileComment: String Read FFileComment;
  26.     Property Files : TStrings Read FFiles;
  27.     Property Entries : TFullZipFileEntries Read FEntries;    
  28.   end;

See the "UnzipFiles" with the TStrings parameter? When you add the filenames to be extracted to this list then you can unzip individual files.

Like in this example which extracts the file "project2.lpi" from the archive "test.zip":
Code: Pascal  [Select]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   unzip: TUnZipper;
  4.   L: TStrings;
  5. begin
  6.   unzip := TUnZipper.Create;
  7.   try
  8.     unzip.FileName := 'test.zip';
  9.     L := TStringList.Create;
  10.     try
  11.       L.Add('project2.lpi');
  12.       unzip.UnzipFiles(L);
  13.     finally
  14.       L.Free;
  15.     end;
  16.   finally
  17.     unzip.Free;
  18.   end;
  19. end;  
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

maurobio

  • Full Member
  • ***
  • Posts: 102
Re: Unzipping ONE file from zip archive
« Reply #3 on: December 04, 2019, 10:59:50 pm »
@wp,

Thanks. I see that UnZipFiles requires a list of file names, even if one wants to unzip only one file (it will be a list of one element, in that case).

Cheers,
UCSD Pascal / Burroughs 6700 / Master Control Program
Lazarus 1.9.3/2.0.4 - FPC 3.0.4 on GNU/Linux Mint 19 ("Tessa"), Windows XP SP3, Windows 7 Professional, Windows 10 Home

wp

  • Hero Member
  • *****
  • Posts: 6471
Re: [SOLVED] Unzipping ONE file from zip archive
« Reply #4 on: December 04, 2019, 11:06:03 pm »
I agree that this is a bit cumbersome. Post a feature request for providing a single-filename UnzipFile method, ideally with a patch. Maybe the maintainer supports this idea and adds the method. That's how Open Source works.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

maurobio

  • Full Member
  • ***
  • Posts: 102
Re: [SOLVED] Unzipping ONE file from zip archive
« Reply #5 on: December 04, 2019, 11:23:35 pm »
@wp,

Sure, I would be glad to help. How can I proceed with posting such a feature request?

Best regards,
UCSD Pascal / Burroughs 6700 / Master Control Program
Lazarus 1.9.3/2.0.4 - FPC 3.0.4 on GNU/Linux Mint 19 ("Tessa"), Windows XP SP3, Windows 7 Professional, Windows 10 Home

maurobio

  • Full Member
  • ***
  • Posts: 102
Re: [SOLVED] Unzipping ONE file from zip archive
« Reply #6 on: December 05, 2019, 12:19:00 am »
Dear ALL,

As a lame workaround, I wrote a simple procedure to extract a single file from an archive:

Code: Pascal  [Select]
  1. procedure ExtractFromArchive(archive, filename: string);
  2. var
  3.   ZipFile: TUnZipper;
  4.   FileList: TStringList;
  5. begin
  6.   ZipFile := TUnZipper.Create;
  7.   try
  8.     ZipFile.FileName := archive;
  9.     FileList := TStringList.Create;
  10.     try
  11.       FileList.Add(filename);
  12.       ZipFile.UnzipFiles(FileList);
  13.     finally
  14.       FileList.Free;
  15.     end;
  16.   finally
  17.     ZipFile.Free;
  18.   end;
  19. end;
  20.  

Hope it may be useful.

Best regards,
UCSD Pascal / Burroughs 6700 / Master Control Program
Lazarus 1.9.3/2.0.4 - FPC 3.0.4 on GNU/Linux Mint 19 ("Tessa"), Windows XP SP3, Windows 7 Professional, Windows 10 Home

wp

  • Hero Member
  • *****
  • Posts: 6471
Re: [SOLVED] Unzipping ONE file from zip archive
« Reply #7 on: December 05, 2019, 12:30:49 am »
OK, since you have not posted a bug report so far, I did it for you: https://bugs.freepascal.org/view.php?id=36399 Use it as a reference for future reports posted by yourself. In general, the link to the bug tracker is shown in the left link bar of the forum.

Adding a patch (i.e. fixing the issue yourself and submitting the difference file(s) increases the chance that a fix is accepted because the developer already gets a solution and only has to evaluate if it makes sense, is coded well etc.

Spend some time in finding a good description of the issue. Always have in mind that the developer must understand what you want to achieve and what is the issue.

To create a patch is more complex than simply writing the bug report. Firstly, you must use the development versions of Lazarus or fpc (trunk), depending on whether the issue belongs to Lazarus or FPC. Use svn to have the up-to-date sources, on Windows use the nice Explorer addon "TortoiseSVN" which is almost self-explanatory. Apply your changes to the unit(s), test everything. Finally create a patch by the svn diff command (or with TortoiseSVN right-click on the Lazarus or FPC folder, select "TortoiseSVN" > "Create patch"). Append the patch file to the bug report.

Usually it is also a good idea to add a demo project in which the developer can see the issue, and which can be used as a test after fixing it.

Find a more detailed description in the wiki: https://wiki.freepascal.org/Creating_A_Patch
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

maurobio

  • Full Member
  • ***
  • Posts: 102
Re: [SOLVED] Unzipping ONE file from zip archive
« Reply #8 on: December 05, 2019, 12:50:31 am »
@wp,

Thanks for the detailed explanation. As a humble user, I do not have the presumption to add patches to such a huge and superb tool as Lazarus and its extensive libraries, but it feels good to be able to actively help, at least with suggestions and (hopefully meaningful) questions.

Best regards,
UCSD Pascal / Burroughs 6700 / Master Control Program
Lazarus 1.9.3/2.0.4 - FPC 3.0.4 on GNU/Linux Mint 19 ("Tessa"), Windows XP SP3, Windows 7 Professional, Windows 10 Home

wp

  • Hero Member
  • *****
  • Posts: 6471
Re: [SOLVED] Unzipping ONE file from zip archive
« Reply #9 on: December 05, 2019, 12:05:46 pm »
The patch has been accepted and extended by some more methods which enhance usability (look at the bugreport). Worth to mention this one which makes the entire process a one-liner: UnzipFile is a class method, i.e. you do not have to create an instance of the TUnzipper:

Code: Pascal  [Select]
  1. procedure TForm1.Button3Click(Sender: TObject);
  2. begin
  3.   TUnzipper.Unzip('test.zip', 'project2.lpi');
  4. end;

The new code will be backported to FPC 3.2.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

maurobio

  • Full Member
  • ***
  • Posts: 102
Re: [SOLVED] Unzipping ONE file from zip archive
« Reply #10 on: December 05, 2019, 12:17:12 pm »
@wp,

This is great!

Thank you very much!
UCSD Pascal / Burroughs 6700 / Master Control Program
Lazarus 1.9.3/2.0.4 - FPC 3.0.4 on GNU/Linux Mint 19 ("Tessa"), Windows XP SP3, Windows 7 Professional, Windows 10 Home