работа с архивами zip

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

работа с архивами zip

Сообщение Luxor » 16.12.2011 11:34:51

В каталоге X:arh/ есть архив XXXX.ZIP
Каким образом можно извлечь содержимое этого архива в текущий каталог "X:arh/"?
Как добавить два файла в один архив YYY.zip?
Luxor
новенький
 
Сообщения: 72
Зарегистрирован: 10.06.2010 19:30:43

Re: работа с архивами zip

Сообщение WAYFARER » 16.12.2011 11:55:09

Аватара пользователя
WAYFARER
энтузиаст
 
Сообщения: 537
Зарегистрирован: 09.10.2009 00:00:04
Откуда: г. Курган

Re: работа с архивами zip

Сообщение Odyssey » 16.12.2011 17:36:02

Я бы использовал классы TZipper/TUnzipper из стандартной библиотеки FreePascal.
http://wiki.freepascal.org/paszlib
Odyssey
энтузиаст
 
Сообщения: 580
Зарегистрирован: 29.11.2007 17:32:24

Re: работа с архивами zip

Сообщение MetallDoctor » 05.09.2013 18:56:04

Что бы не плодить темы без необходимости – спрошу в этой.
Такая программка (в двух словах – хочу скормить папку, в которую накачивается музыка с сервиса thankyou.ru в архивах, что бы программка вытащила музыку, разложила по папкам, поправила имена файлов и папок и id3 теги так, как мне удобно, я думаю проще написать программу, чем по новой перелопачивать 15+ ГБ архивов):
Код: Выделить всё
unit TankYouExtractor;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  ExtCtrls, Zipper;

type

  { TFormThankYouExtractor }

  TFormThankYouExtractor = class(TForm)
    SourceBtn: TButton;
    DestinationBtn: TButton;
    GoBtn: TButton;
    procedure GoBtnClick(Sender: TObject);
    procedure SourceBtnClick(Sender: TObject);
    procedure DestinationBtnClick(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

  TInfo = RECORD
    Artist, Album:STRING;
    Year:Integer;
    Tracks:ARRAY OF STRING;
  end;

var
  FormThankYouExtractor: TFormThankYouExtractor;
  Source, Destination: STRING;
  Albums: TStringList;

implementation

{$R *.lfm}

{ TFormThankYouExtractor }

//Полный оригинальный код для копирования:
//http://delphiworld.narod.ru/base/copy_dirs.html
//Правки для Lazarus сделаны на основе:
//http://freepascal.ru/forum/viewtopic.php?t=9259 (содержит ошибки)
function GetListAlbums(SourceDir: string): Boolean;
var
  SR: TSearchRec;
  I: Integer;
begin
  Result := False;
  SourceDir := IncludeTrailingBackslash(SourceDir);
  I := FindFirstUTF8(SourceDir + '*.zip', faAnyFile, SR);
  try
    while I = 0 do begin
      if(SR.Name<>'')and(SR.Name<>'.')and(SR.Name<>'..')AND(SR.Attr<>faDirectory)then
        Albums.Add(Copy(SR.Name,1, Length(SR.Name)-4));
      I := FindNextUTF8(SR)
    end;
    Result := True
  finally
    SysUtils.FindClose(SR);
  end;
end;

procedure TFormThankYouExtractor.SourceBtnClick(Sender: TObject);
VAR
  SD: TSelectDirectoryDialog;
begin
  sd := TSelectDirectoryDialog.Create(Application);
  if sd.Execute then Source:= IncludeTrailingBackslash(sd.FileName);
  FreeAndNil(sd);
end;

procedure TFormThankYouExtractor.DestinationBtnClick(Sender: TObject);
VAR
  SD: TSelectDirectoryDialog;
begin
  sd := TSelectDirectoryDialog.Create(Application);
  if sd.Execute then Destination := IncludeTrailingBackslash(sd.FileName);
  FreeAndNil(sd);
end;

PROCEDURE UnZip(Zip:STRING);
var
  UnZipper: TUnZipper;
begin
  UnZipper := TUnZipper.Create;
  try
    UnZipper.FileName := Source + Zip + '.zip';
    UnZipper.OutputPath := IncludeTrailingBackslash(Source + Zip);
    UnZipper.Examine;
    UnZipper.UnZipAllFiles;
  finally
    UnZipper.Free;
  end;
end;

FUNCTION GetValue(S:STRING):STRING;
BEGIN
  Result:=S
end;

PROCEDURE GetInfo(VAR Info: TInfo; Folder: STRING);
VAR
  ReadMe,F:TextFile;
  S:String;
  N,I:Integer;
BEGIN
  TRY
    Assign (ReadMe, Folder+'readme.txt');
    Reset (ReadMe);
    IF NOT EoF(ReadMe) THEN BEGIN
      ReadLn(ReadMe,S);
      WHILE (Pos('01.', S) = 0) AND NOT EoF(ReadMe) DO BEGIN
        IF Pos('Исполнитель:',S)=1 THEN Info.Artist:=GetValue(S);
        IF Pos('Название альбома:',S)=1 THEN Info.Album:=GetValue(S);
        IF Pos('Год выпуска альбома:',S)=1 THEN Info.Year:=StrToInt(GetValue(S));
        ReadLn(ReadMe,S)
      end;
      Info.Album:=IntToStr(Info.Year)+' – '+Info.Album;
      N:=0;
      IF Pos('01.',S)=1 THEN REPEAT
          Inc(N);
          SetLength(Info.Tracks, Length(Info.Tracks)+1);
          Info.Tracks[N]:=(Copy(S,5,Length(S)-15));
          IF N<9 THEN Info.Tracks[N]:='0'+IntToStr(N+1)+Info.Tracks[N]
          ELSE Info.Tracks[N]:=IntToStr(N+1)+Info.Tracks[N];
          ReadLn(ReadMe,S);
      UNTIL (Length(S)=0) or EoF(ReadMe);
      TRY
        Assign(F, Destination+'txt.txt');
        ReWrite(F);
        WriteLn(F,Info.Artist);
        WriteLn(F,Info.Album);
        WriteLn(F,Info.Year);
        FOR I:=0 TO N DO WriteLn(F,Info.Tracks[I])
      finally
        Close(F);
      end;
    END ELSE ShowMessage('readme.txt пуст')
  EXCEPT
    ShowMessage('Проблемы при обращении к readme.txt')
  end;
  Close(F);
end;

procedure TFormThankYouExtractor.GoBtnClick(Sender: TObject);
VAR
  I: Integer;
  Info: TInfo;
begin
  TRY
    Albums := TStringList.Create;
    IF Source = '' THEN
      ShowMessage('Каталог с архивами не указан')
    ELSE
      IF Destination = '' then
        ShowMessage('Целевой каталог не указан')
      ELSE BEGIN
        GetListAlbums(Source);
        FOR I := 0 TO (Albums.Count-1) DO BEGIN
          UnZip(Albums[I]);
          GetInfo(Info, IncludeTrailingBackslash(
           IncludeTrailingBackslash(Source)+Albums[I]))
        end
    end;
  finally
    Albums.Free
  end;
end;

end.
До самого интересного программа ещё не дошла.
Сейчас падает при начале работы с архивом (на строке «UnZipper.Examine;», если её закоментировать – на следующей). Весь код для процедуры разархивации – отсюда. Сам архив целый и живой, проходит тестирование 7z нормально, права все есть, руками открывается. Тестирую на этом, если вдруг это вопрос алгоритмов упаковки.

Ошибка Unable to open file "%FullFilePathAndName%" выглядит так.

Если бы писал только для себя и на 1 раз – остановился бы на использовании 7z.exe и GNU/Linux-аналога для другого компа, но хочется полноценной кроссплатформерности и программной независимости единого продукта.

Если TUnZipper – не очень удачная вещь, то, буду благодарен и за совет, что показывает себя лучше.

P.S. Если кто-то уже работал с id3 и мимоходом скинет ссылочку на проверенные примеры кода для Lazarus'а – буду сильно благодарен, сам ещё не искал.
MetallDoctor
незнакомец
 
Сообщения: 9
Зарегистрирован: 24.08.2010 21:38:33

Re: работа с архивами zip

Сообщение Лекс Айрин » 06.09.2013 00:08:20

MetallDoctor, судя по тексту ошибки траблы с правами. Примерный текст сообщения "файл не может быть открыт". Второй вариант -- неправильная кодировка в строке адреса. В Лазарусе UTF8 а в системе, если судить по окну сообщения, ANSI (win1251). То, что имя файла нормально отображается ничего не значит.

ЗЫ: в следующий раз указывайте ось и версию lazarus/FPC.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: работа с архивами zip

Сообщение MetallDoctor » 06.09.2013 12:08:10

С правами – навряд ли. Программа выполняется от моего имени, а с правами там полный порядок.

Перепроверил (хотя, казалось, что уже так делал и отмёл этот вариант) с папками без русских путей – C:\1\arch.zip и C:\2\ – отработало нормально

Мне казалось, что в viewtopic.php?t=9259 описывается кроссплатформерное решение.
Подскажите тогда, пожалуйста, как сделать реально кроссплатформерный вариант, что бы не стругать две параллельных ветки?

P.S. Добавил в подпись.
MetallDoctor
незнакомец
 
Сообщения: 9
Зарегистрирован: 24.08.2010 21:38:33

Re: работа с архивами zip

Сообщение Лекс Айрин » 06.09.2013 13:09:20

MetallDoctor писал(а): с папками без русских путей – C:\1\arch.zip и C:\2\ – отработало нормально


Значит, точно надо играться с кодировками. Попробуй путь задаваемый функции пропустить через функцию Utf8toSys. (если не хочешь заморачиваться с условной компиляцией, то и в других осях можно будет оставить)
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: работа с архивами zip

Сообщение Vadim » 09.09.2013 05:24:11

MetallDoctor
Архив, который Вы открываете, какой имеет размер?
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 222

Рейтинг@Mail.ru