Categories: wxWidgets

Быстрый способ упаковки содержимого папки в ZIP-архив

В wxWidgets есть такая отличная штука, как wxDirTraverser.
Что это и с чем его едят? Официальная документация говорит нам вот что:

wxDirTraverser is an abstract interface which must be implemented by objects passed to wxDir::Traverse() function.
Как по мне, довольно странное описание %), ничего толкового мы из него не узнаем. Тогда идем смотреть описание wxDir::Traverse():
Enumerate all files and directories under the given directory recursively calling the element of the provided wxDirTraverser object for each of them.
Уже лучше, оказывается, объект wxDirTraverser вызывается для каждого найденного объекта в указанном каталоге. Поиск выполняется рекурсивно для всех подкаталогов.
Итак, чем нам может помочь эта информация. Из документации видно, что у класса wxDirTraverser есть методы, которые вызываются для каждого файла или подкаталога (соответственно OnFile() и OnDir()), в которые передается путь найденного файла или каталога. Это значит что, получая имя каждого файла, мы можем сразу же добавить этот файл в архив без необходимости получения списка всех файлов и подкаталогов в массив (как мы бы сделали при использовании wxDir::GetAllFiles()).
Как это реализовано, смотрим ниже:

Dir Travaerser:

#ifndef _WX_DIR_TRAVERSER_ZIP_H
#define _WX_DIR_TRAVERSER_ZIP_H

#include <wx/wx.h>
#include <wx/dir.h>
#include <wx/zipstrm.h>
#include <wx/filename.h>
#include <wx/wfstream.h>

class wxDirTraverserZIP : public wxDirTraverser
{
public:
 wxDirTraverserZIP(wxZipOutputStream & stream, const wxString & baseDir)
  : m_Stream(stream), m_BaseDir(baseDir) { }

 virtual wxDirTraverseResult OnFile(const wxString& filename)
 {
  do
  {
   wxFileName newFileName(filename);
   newFileName.MakeRelativeTo(m_BaseDir);
   if(!m_Stream.PutNextEntry(newFileName.GetFullPath()))
   {
    break;
   }
   wxFileInputStream in(filename);
   if(!in.IsOk())
   {
    break;
   }
   m_Stream.Write(in);
   return wxDIR_CONTINUE;
  }
  while(false);
  return wxDIR_STOP;
 }

 virtual wxDirTraverseResult OnDir(const wxString& dirname)
 {
  return wxDIR_CONTINUE;
 }

private:
 wxZipOutputStream & m_Stream;
 wxString m_BaseDir;
};

#endif

Usage:

bool PackFolder(const wxString & srcFolderName, const wxString & zipFileName)
{
 do
 {
  wxFFileOutputStream out(zipFileName);
  if(!out.IsOk()) break;
  wxCSConv conv(wxT("cp-866"));
  wxZipOutputStream zip(out, 9, conv);
  if(!zip.IsOk()) break;
  wxDirTraverserZIP traverser(zip, srcFolderName);
  wxDir srcDir(srcFolderName);
  if(srcDir.Traverse(traverser, wxEmptyString) == (size_t)-1) break;
  return true;
 }
 while(false);
 return false;
}
...
// Pack the folder
if(!PackFolder(wxT("c:\\test"), wxT("c:\\some.zip")))
{
//Handle error here
}
T-Rex

View Comments

  • Sorry I can't read most of the writing on this website, but I'd very much like to use the DirTraverserZIP class you've written in a GPL project. Is that ok?

    Thanks for your good work!

    Cheers,
    Gerald

Share
Published by
T-Rex

Recent Posts

Разработка кроссплатформенных модульных приложений на C++ с библиотекой wxWidgets

Введение Уже долгое время не пишу статьи о разработке, хотя сам процесс написания мне очень…

10 years ago

wxWidgets App With Plugins (Windows/Linux/Mac) – Sample Source Code

I can see that there is still a lot of topics at wxWidgets forums related…

11 years ago

wxToolBox is Now Open-Source!

I've just published the source code of wxToolBox component and a couple of sample apps at…

11 years ago

Microsoft Kinect Helper Library and Sample for wxWidgets

Microsoft released their Kinect SDK several days ago. So, for those wxWidgets developers who are…

13 years ago

wxJSON 1.1.0 Released

JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to…

14 years ago

wxRuby. Оно даже работает!

Вдохновленнный читаемой нынче книгой My Job Went to India: 52 Ways to Save Your Job…

15 years ago