В wxWidgets есть такая отличная штука, как wxDirTraverser.
Что это и с чем его едят? Официальная документация говорит нам вот что:
Как по мне, довольно странное описание %), ничего толкового мы из него не узнаем. Тогда идем смотреть описание wxDir::Traverse():
Уже лучше, оказывается, объект
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
}
2 Comments
Gerald
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
T-Rex
Yes, this is ok. It is free for both commercial and non-commercial use.