⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arc.tex

📁 很牛的GUI源码wxWidgets-2.8.0.zip 可在多种平台下运行.
💻 TEX
📖 第 1 页 / 共 2 页
字号:
\subsection{Generic archive programming}\label{wxarcgeneric}\helpref{Archive formats such as zip}{wxarc}Also see \helpref{wxFileSystem}{fs} for a higher level interface thatcan handle archive files in a generic way.The specific archive classes, such as the wxZip classes, inherit fromthe following abstract classes which can be used to write code that canhandle any of the archive types:\begin{twocollist}\twocolwidtha{5cm}\twocolitem{\helpref{wxArchiveInputStream}{wxarchiveinputstream}}{Input stream}\twocolitem{\helpref{wxArchiveOutputStream}{wxarchiveoutputstream}}{Output stream}\twocolitem{\helpref{wxArchiveEntry}{wxarchiveentry}}{Holds the meta-data for anentry (e.g. filename)}\end{twocollist}In order to able to write generic code it's necessary to be able to createinstances of the classes without knowing which archive type is being used.To allow this there is a class factory for each archive type, derived from \helpref{wxArchiveClassFactory}{wxarchiveclassfactory}, that can createthe other classes.For example, given {\it wxArchiveClassFactory* factory}, streams andentries can be created like this:\begin{verbatim}    // create streams without knowing their type    auto_ptr<wxArchiveInputStream> inarc(factory->NewStream(in));    auto_ptr<wxArchiveOutputStream> outarc(factory->NewStream(out));    // create an empty entry object    auto_ptr<wxArchiveEntry> entry(factory->NewEntry());\end{verbatim}For the factory itself, the static member \helpref{wxArchiveClassFactory::Find()}{wxarchiveclassfactoryfind}.can be used to find a class factory that can handle a given fileextension or mime type. For example, given {\it filename}:\begin{verbatim}    const wxArchiveClassFactory *factory;    factory = wxArchiveClassFactory::Find(filename, wxSTREAM_FILEEXT);    if (factory)        stream = factory->NewStream(new wxFFileInputStream(filename));\end{verbatim}{\it Find} does not give away ownership of the returned pointer, so itdoes not need to be deleted.There are similar class factories for the filter streams that handle thecompression and decompression of a single stream, such as wxGzipInputStream.These can be found using \helpref{wxFilterClassFactory::Find()}{wxfilterclassfactoryfind}.For example, to list the contents of archive {\it filename}:\begin{verbatim}    auto_ptr<wxInputStream> in(new wxFFileInputStream(filename));    if (in->IsOk())    {        // look for a filter handler, e.g. for '.gz'        const wxFilterClassFactory *fcf;        fcf = wxFilterClassFactory::Find(filename, wxSTREAM_FILEEXT);        if (fcf) {            in.reset(fcf->NewStream(in.release()));            // pop the extension, so if it was '.tar.gz' it is now just '.tar'            filename = fcf->PopExtension(filename);        }        // look for a archive handler, e.g. for '.zip' or '.tar'        const wxArchiveClassFactory *acf;        acf = wxArchiveClassFactory::Find(filename, wxSTREAM_FILEEXT);        if (acf) {            auto_ptr<wxArchiveInputStream> arc(acf->NewStream(in.release()));            auto_ptr<wxArchiveEntry> entry;            // list the contents of the archive            while ((entry.reset(arc->GetNextEntry())), entry.get() != NULL)                std::wcout << entry->GetName().c_str() << "\n";        }        else {            wxLogError(_T("can't handle '%s'"), filename.c_str());        }    }\end{verbatim}\subsection{Archives on non-seekable streams}\label{wxarcnoseek}\helpref{Archive formats such as zip}{wxarc}In general, handling archives on non-seekable streams is done in the sameway as for seekable streams, with a few caveats.The main limitation is that accessing entries randomly using \helpref{OpenEntry()}{wxarchiveinputstreamopenentry} is not possible, the entries can only be accessed sequentially in the order they are stored within the archive.For each archive type, there will also be other limitations which willdepend on the order the entries' meta-data is stored within the archive.These are not too difficult to deal with, and are outlined below.\wxheading{PutNextEntry and the entry size}When writing archives, some archive formats store the entry size beforethe entry's data (tar has this limitation, zip doesn't). In this casethe entry's size must be passed to \helpref{PutNextEntry()}{wxarchiveoutputstreamputnextentry} or an erroroccurs.This is only an issue on non-seekable streams, since otherwise the archiveoutput stream can seek back and fix up the header once the size of theentry is known.For generic programming, one way to handle this is to supply the sizewhenever it is known, and rely on the error message from the outputstream when the operation is not supported.\wxheading{GetNextEntry and the weak reference mechanism}Some archive formats do not store all an entry's meta-data before theentry's data (zip is an example). In this case, when reading from anon-seekable stream, \helpref{GetNextEntry()}{wxarchiveinputstreamgetnextentry} can only return a partially populated \helpref{wxArchiveEntry}{wxarchiveentry}object - not all the fields are set.The input stream then keeps a weak reference to the entry object andupdates it when more meta-data becomes available. A weak reference beingone that does not prevent you from deleting the wxArchiveEntry object - theinput stream only attempts to update it if it is still around.The documentation for each archive entry type gives the detailsof what meta-data becomes available and when. For generic programming,when the worst case must be assumed, you can rely on all the fieldsof wxArchiveEntry being fully populated when GetNextEntry() returns,with the the following exceptions:\begin{twocollist}\twocolwidtha{3cm}\twocolitem{\helpref{GetSize()}{wxarchiveentrysize}}{Guaranteed to beavailable after the entry has been read to \helpref{Eof()}{wxinputstreameof},or \helpref{CloseEntry()}{wxarchiveinputstreamcloseentry} has been called}\twocolitem{\helpref{IsReadOnly()}{wxarchiveentryisreadonly}}{Guaranteed tobe available after the end of the archive has been reached, i.e. afterGetNextEntry() returns NULL and Eof() is true}\end{twocollist}This mechanism allows \helpref{CopyEntry()}{wxarchiveoutputstreamcopyentry}to always fully preserve entries' meta-data. No matter what order orderthe meta-data occurs within the archive, the input stream will alwayshave read it before the output stream must write it.\wxheading{wxArchiveNotifier}Notifier objects can be used to get a notification whenever an inputstream updates a \helpref{wxArchiveEntry}{wxarchiveentry} object's datavia the weak reference mechanism.Consider the following code which renames an entry in an archive.This is the usual way to modify an entry's meta-data, simply set therequired field before writing it with \helpref{CopyEntry()}{wxarchiveoutputstreamcopyentry}:\begin{verbatim}    auto_ptr<wxArchiveInputStream> arc(factory->NewStream(in));    auto_ptr<wxArchiveOutputStream> outarc(factory->NewStream(out));    auto_ptr<wxArchiveEntry> entry;    outarc->CopyArchiveMetaData(*arc);    while (entry.reset(arc->GetNextEntry()), entry.get() != NULL) {        if (entry->GetName() == from)            entry->SetName(to);        if (!outarc->CopyEntry(entry.release(), *arc))            break;    }    bool success = arc->Eof() && outarc->Close();\end{verbatim}However, for non-seekable streams, this technique cannot be used forfields such as \helpref{IsReadOnly()}{wxarchiveentryisreadonly},which are not necessarily set when \helpref{GetNextEntry()}{wxarchiveinputstreamgetnextentry} returns. Inthis case a \helpref{wxArchiveNotifier}{wxarchivenotifier} can be used:\begin{verbatim}class MyNotifier : public wxArchiveNotifier{public:    void OnEntryUpdated(wxArchiveEntry& entry) { entry.SetIsReadOnly(false); }};\end{verbatim}The meta-data changes are done in your notifier's \helpref{OnEntryUpdated()}{wxarchivenotifieronentryupdated} method,then \helpref{SetNotifier()}{wxarchiveentrynotifier} is called beforeCopyEntry():\begin{verbatim}    auto_ptr<wxArchiveInputStream> arc(factory->NewStream(in));    auto_ptr<wxArchiveOutputStream> outarc(factory->NewStream(out));    auto_ptr<wxArchiveEntry> entry;    MyNotifier notifier;    outarc->CopyArchiveMetaData(*arc);    while (entry.reset(arc->GetNextEntry()), entry.get() != NULL) {        entry->SetNotifier(notifier);        if (!outarc->CopyEntry(entry.release(), *arc))            break;    }    bool success = arc->Eof() && outarc->Close();\end{verbatim}SetNotifier() calls OnEntryUpdated() immediately, then the inputstream calls it again whenever it sets more fields in the entry. SinceOnEntryUpdated() will be called at least once, this technique alwaysworks even when it is not strictly necessary to use it. For example,changing the entry name can be done this way too and it works on seekablestreams as well as non-seekable.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -