0

I am using the following code to extract files from SevenZIP archive. It works well with single-volume archives, but fails with multi-volume.

procedure TMyClass.ExtractArchive(AInputFile:String;AOutputDir:String);
var
 LArchive:TJcl7zDecompressArchive;
begin
 LArchive:=TJcl7zDecompressArchive.Create(AInputFile);
 try
  LArchive.OnProgress:=ExtractProgress;
  LArchive.ListFiles();
  try
   LArchive.ExtractAll(AOutputDir);
  except
   on e:Exception do
    LogError(e);
  end;
 finally
  LArchive.Free();
 end;
end;

It seems that volumes of SevenZip are just files split in half (in the opposite of RAR and ZIP archives). Do I have to manually prepare combined stream (of all volumes as one) all by myself? Or JCL will handle it automatically somehow?

cschneid
  • 10,237
  • 1
  • 28
  • 39
Flash
  • 466
  • 6
  • 16

1 Answers1

2

The Jcl 7zip classes don't handle reading existing split archives well. It has callbacks to get volume names, but if they're not on separate removable drives it's easiest to just add all the volumes manually before you open it:

if AnsiEndsText(AInputFile, '.001') then
begin 
  LArchive := TJcl7zDecompressArchive.Create(AInputFile, GetFileSize(AInputFile, nil));
  for VolumeIndex := 2 to 999 do begin
    VolumeName := ChangeFileExt(AInputFile, Format('.%.3d', [VolumeIndex]));
    VolumeSize := GetFileSize(VolumeName, nil);
    if VolumeSize = INVALID_FILE_SIZE then
      Break;
    LArchive.AddVolume(VolumeName, VolumeSize);
  end
end
else
  LArchive := TJcl7zDecompressArchive.Create(AInputFile);
Zoë Peterson
  • 13,094
  • 2
  • 44
  • 64
  • Presumably abbrevia does a better job? – David Heffernan Jan 27 '15 at 20:47
  • OT: Are you aware of this issue (http://stackoverflow.com/questions/27821277/why-are-the-delphi-zlib-and-zip-libraries-so-slow-under-64-bit)? I guess it might have an impact on abbrevia if it uses stock Emba zlib. – David Heffernan Jan 27 '15 at 20:49
  • @DavidHeffernan Abbrevia doesn't handle .7z archives, so, _no_, but yes, it's .zip splitting behavior works and is fully automatic. v5.0 improved that quite a bit. – Zoë Peterson Jan 28 '15 at 16:12
  • 2
    @DavidHeffernan Abbrevia actually includes a clean room Pascal implementation of the DEFLATE algorithm; it doesn't rely on zlib at all. The 32-bit one was a bit slower than zlib and the results were about 10% larger, but it also supports the DEFLATE64 variant, which zlib doesn't. I haven't benchmarked the 64-bit variant. In any case, since Embarcadero is paying to fork Abbrevia and hasn't been willing to work with me to backport the changes, I'm no longer actively maintaining the original project. – Zoë Peterson Jan 28 '15 at 16:19
  • I have almost identical code and doesn't work: http://stackoverflow.com/questions/36505966/how-to-open-multivolume-archive-with-jedis-tjcldecompressarchive – Tom Apr 08 '16 at 17:55
  • @Tom Passing in the file sizes is not optional. I don't remember the details anymore, but the built-in code does not work without it – Zoë Peterson Apr 08 '16 at 18:08
  • @ZoëPeterson: I added file sizes and it's still the same thing. Are you sure your code above worked? – Tom Apr 08 '16 at 18:12
  • 1
    @Tom The code we're using internally looks virtually identical to that, and there don't appear to be any changes to the JCL that would have affected it. The only difference is that we're using TJcl7zUpdateArchive instead of TJcl7zDecompressArchive – Zoë Peterson Apr 11 '16 at 21:47
  • @ZoëPeterson Thanks a log. It works for me now on 7z files. Still not on RAR ones. I suppose there's a bug. – Tom Apr 12 '16 at 00:19