В 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.