zipper упаковка ODT файлов[Решено]

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

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

Re: zipper упаковка ODT файлов

Сообщение Odyssey » 20.08.2010 19:08:12

скалогрыз писал(а):Надеюсь Zipper более адекватен в распаковке файлов, чем unzip.
Не пробовал, но он основан на paszlib, а в багтрекере Марко писал что paszlib с распаковкой справляется.
скалогрыз писал(а):Кстати, патч сделал!
Спасибо, в любом случае чем меньше багов в RTL, тем лучше.
Odyssey
энтузиаст
 
Сообщения: 580
Зарегистрирован: 29.11.2007 17:32:24

Re: zipper упаковка ODT файлов

Сообщение ifrost » 10.11.2010 23:37:53

Подскажите пожалуйста, как запаковать TZipper-ом какую-либо директорию вместе со всем ее содержимым? FindAllFiles из FileUtils возвращает только файлы, а вот пустые подпапки, которых в распакованном odt-файле много, не выдает.
ifrost
новенький
 
Сообщения: 21
Зарегистрирован: 13.11.2009 09:19:51

Re: zipper упаковка ODT файлов

Сообщение Odyssey » 11.11.2010 00:06:44

Как вариант, можно сделать свою функцию на основе FindFirst/FindNext/FindClose, которая обходила бы файлы и рекурсивно вложенные директории и добавляла бы в список всё, в том числе числе пустые директории.
Odyssey
энтузиаст
 
Сообщения: 580
Зарегистрирован: 29.11.2007 17:32:24

Re: zipper упаковка ODT файлов

Сообщение Maxizar » 11.11.2010 16:34:10

ifrost писал(а):Подскажите пожалуйста, как запаковать TZipper-ом какую-либо директорию вместе со всем ее содержимым? FindAllFiles из FileUtils возвращает только файлы, а вот пустые подпапки, которых в распакованном odt-файле много, не выдает.

Я вот для своей программки по диплому написал классы и модули для работы с ODT пока все не доходят руки допилить... но вот могу предложить выдранный код одного из методов общего класса для сохранения директории в зип архив... при этом я не обрабатываю пустые коталоги они просто не нужны Open Office пойемет и так... ну а пробегаю по старинке... Как только допишу выложу побеседуем... сейчас пока реализовано:
1. В классе прородителе для всех (Write, Calc)
Открытие из файла
Сохранение в файл
Получение и запись мета данных
для ODT
добавление текста, шрифта
добавление свойства параграфа
вставка текста в существующий параграф
вставка картинки из файла или из битмама в файл
и что то еще уже не помню...
ТАк что кому интересно ждите.. Совместными усилиями отшлифуем может будет полезно :)
Код: Выделить всё
procedure TOODocument.SaveToFile(const FileName: String);
var Zip:TZipper;
    F:TZipFileEntries;
Function ReplaceSlash(const OldFileName:string):String;
var I:Integer;
begin
  Result:=OldFileName;
  For I:=1 to Length(OldFileName) do
     if Result[I]='\' then  Result[I]:='/';
end;

Procedure RetZipFiles(var ZipFile:TZipFileEntries; Const BaseDir:String);
var
  iIndex : Integer;
  SearchRec : TSearchRec;
  sFileName,Dir : String;
begin

  if (BaseDir='') or (not DirectoryExists(BaseDir)) then Exit; //Ааа нас обманули :)

  Dir := IncludeTrailingPathDelimiter(BaseDir);      //для Win ='\' Linux='/'
  iIndex := FindFirst(Dir+'*.*', faAnyFile, SearchRec);

  while iIndex = 0 do
    begin
     sFileName := Dir+SearchRec.Name;

     if SearchRec.Attr = faDirectory then
       begin  //нашли директорию
        if (SearchRec.Name <> '' ) and (SearchRec.Name <> '.')
            and (SearchRec.Name <> '..') then RetZipFiles(ZipFile,sFileName);
       end
         else    //нашли файл, добовляем его к списку для архивации
          ZipFile.AddFileEntry(sFileName,
                             ReplaceSlash(ExtractRelativePath(FTempPath,sFileName)));

   iIndex := FindNext(SearchRec);
   end;
  FindClose(SearchRec);
end;

Procedure SaveDoc(var XMLDoc: TXMLDocument;
  const XMLFileName: String);
begin
  if XMLDoc<>Nil then
  WriteXMLFile(XMLDoc, XMLFileName);
end;
begin
    //Сохранение XMLDoc в соответствующие XML файлы
  SaveDoc(FContent,FTempPath+'content.xml'); //content.xml
  SaveDoc(FManifest,IncludeTrailingPathDelimiter(FTempPath+'META-INF')+'manifest.xml');//META-INF/manifest.xml
  SaveDoc(FMeta,FTempPath+'meta.xml');     //meta.xml

   F:=TZipFileEntries.Create(TZipFileEntry);

   Zip:=TZipper.Create;
   Zip.FileName:=FileName;
   RetZipFiles(F,FTempPath);

   Try
    Zip.ZipFiles(F);
   finally
    Zip.Free;
    F.Free;
   end;

end;
Maxizar
постоялец
 
Сообщения: 385
Зарегистрирован: 20.03.2010 19:48:14

Re: zipper упаковка ODT файлов

Сообщение ViTality » 11.11.2010 20:11:08

тоже одно время думал о таком способе создания "офисных" отчетов/экспортов из своей програмки.
взять пустой odt посмотреть содержимое подготовить пару шаблонов и вставлять текст в определенные места xml-файлов.
И ведь такой же принцип можно применять для работы с docx. там же тоже архив с xml-ями......
ViTality
постоялец
 
Сообщения: 308
Зарегистрирован: 05.10.2007 15:12:02

Re: zipper упаковка ODT файлов

Сообщение ifrost » 13.11.2010 00:47:37

Вот мой вариант запаковки ODT:
Код: Выделить всё
procedure TfrmMain.btnZipClick(Sender: TObject);
var
  Zip: TZipper;
  FilesForZip: TZipFileEntries;
  FileList: TStringList;
  i: integer;
begin
  Application.ProcessMessages;
  try
    Screen.Cursor := crHourGlass;
    //Из полного списка файлов возвращаемого функцией FindAll добавляем
    //в цикле в объект FilesForZip относительные(ExtractRelativepath) пути
    //к файлам и папкам для архивации, при этом разделители директорий
    //меняются на юниксовые (UnixDirSepatator). К папкам добавляется
    //конечный слеш (AppendPathDelimEx)
    FileList := TStringList.Create;
    FileList := FindAll(TempFolder);
    FilesForZip := TZipFileEntries.Create(TZipFileEntry);
    for i := 0 to FileList.Count - 1 do
    begin
      FilesForZip.AddFileEntry(FileList[i],
        UnixDirSepatator(ExtractRelativepath(TempFolder,
        AppendPathDelimEx(FileList[i]))));
    end;
    Zip := TZipper.Create;
    Zip.FileName := 'document.odt';
    Zip.ZipFiles(FilesForZip);
  finally
    Zip.Free;
    FileList.Free;
    FilesForZip.Free;
    Screen.Cursor := crDefault;
  end;
end;

А это небольшой модуль (FileUtilEx) в который я вынес вспомогательные функции:
Код: Выделить всё
unit FileUtilEx;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, StrUtils;

type
  {** TFileDirSearcher - класс для поиска файлов и папок }
  TFileDirSearcher = class(TFileSearcher)
  private
    FList: TStrings;
  protected
    procedure DoFileFound; override;
    procedure DoDirectoryFound; override;
  public
    constructor Create(AList: TStrings);
  end;

{** Функция возвращает список всех файлов и (под)директорий по указанному пути }
function FindAll(const APath: string): TStringList;
{** Исправляет слеши в стиле Windows }
function WinDirSepatator(const APath: string): string;
{** Исправляет слеши в стиле Unix }
function UnixDirSepatator(const APath: string): string;
{** Добавляет конечный слеш только если последний элемент пути - директория }
function AppendPathDelimEx(const APath: string): string;

implementation

function FindAll(const APath: string): TStringList;
var
  Searcher: TFileDirSearcher;
begin
  Result := TStringList.Create;
  Searcher := TFileDirSearcher.Create(Result);
  try
    Searcher.Search(APath);
  finally
    Searcher.Free;
  end;
end;

function WinDirSepatator(const APath: string): string;
begin
  Result := AnsiReplaceStr(APath, '/', '\');
end;

function UnixDirSepatator(const APath: string): string;
begin
  Result := AnsiReplaceStr(APath, '\', '/');
end;

function AppendPathDelimEx(const APath: string): string;
begin
  if (FileGetAttr(APath) and faDirectory) <> 0 then
    Result := AppendPathDelim(APath)
  else
    Result := APath;
end;

{ TFileDirSearcher }

procedure TFileDirSearcher.DoFileFound;
begin
  FList.Add(FileName);
end;

procedure TFileDirSearcher.DoDirectoryFound;
begin
  FList.Add(FileName);
end;

constructor TFileDirSearcher.Create(AList: TStrings);
begin
  FList := AList;
end;

end.

Может кому пригодится...
ifrost
новенький
 
Сообщения: 21
Зарегистрирован: 13.11.2009 09:19:51

Re: zipper упаковка ODT файлов

Сообщение dunin » 16.08.2011 14:50:50

Odyssey писал(а):Извиняюсь, если отнял у кого-то работу. ODF вполне сносно собирается TZipper'ом. Как обычно, из-за ерунды большие проблемы...
...
Т.е. все разделители пути в архивированных файлах должны быть "/". Пустые директории можно тоже включать в архив, при этом в конце архивного имени нужно ставить разделитель.
...

Odyssey, продолжительные аплодисменты и огромное спасибо!
Убил кучу времени с zipper-ом, пока не догадался поискать как следует по форуму. :?
Аватара пользователя
dunin
энтузиаст
 
Сообщения: 634
Зарегистрирован: 02.05.2007 13:18:11
Откуда: Тољя††и

Пред.

Вернуться в Lazarus

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

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

Рейтинг@Mail.ru
cron