]> git.saurik.com Git - wxWidgets.git/blobdiff - docs/latex/wx/arc.tex
Use const
[wxWidgets.git] / docs / latex / wx / arc.tex
index f84fc46f6ba7b356cb102c496880f0bc3029f522..836828ae1b334a6f3fcbcd80f57f4270fd3f58ef 100644 (file)
@@ -10,7 +10,8 @@
 \section{Archive formats such as zip}\label{wxarc}
 
 The archive classes handle archive formats such as zip, tar, rar and cab.
-Currently only the wxZip classes are included.
+Currently \helpref{wxZip}{wxzipinputstream}
+and \helpref{wxTar}{wxtarinputstream} classes are included.
 
 For each archive type, there are the following classes (using zip here
 as an example):
@@ -51,41 +52,43 @@ For example:
     wxFFileOutputStream out(_T("test.zip"));
     wxZipOutputStream zip(out);
     wxTextOutputStream txt(zip);
+    wxString sep(wxFileName::GetPathSeparator());
 
     zip.PutNextEntry(_T("entry1.txt"));
-    txt << _T("Some text for entry1\n");
+    txt << _T("Some text for entry1.txt\n");
 
-    zip.PutNextEntry(_T("entry2.txt"));
-    txt << _T("Some text for entry2\n");
+    zip.PutNextEntry(_T("subdir") + sep + _T("entry2.txt"));
+    txt << _T("Some text for subdir/entry2.txt\n");
 
 \end{verbatim}
 
+The name of each entry can be a full path, which makes it possible to
+store entries in subdirectories.
+
 
 \subsection{Extracting an archive}\label{wxarcextract}
 
 \helpref{Archive formats such as zip}{wxarc}
 
-\helpref{GetNextEntry()}{wxarchiveinputstreamgetnextentry} returns an
-entry object containing the meta-data for the next entry in the archive
-(and gives away ownership). Reading from the input stream then returns
-the entry's data. Eof() becomes true after an attempt has been made to
-read past the end of the entry's data.
+\helpref{GetNextEntry()}{wxarchiveinputstreamgetnextentry} returns a pointer
+to entry object containing the meta-data for the next entry in the archive
+(and gives away ownership). Reading from the input stream then returns the
+entry's data. Eof() becomes true after an attempt has been made to read past
+the end of the entry's data.
 
 When there are no more entries, GetNextEntry() returns NULL and sets Eof().
 
 \begin{verbatim}
-    wxDEFINE_SCOPED_PTR_TYPE(wxZipEntry);
-    wxZipEntryPtr entry;
+    auto_ptr<wxZipEntry> entry;
 
     wxFFileInputStream in(_T("test.zip"));
     wxZipInputStream zip(in);
-    wxTextInputStream txt(zip);
-    wxString data;
 
     while (entry.reset(zip.GetNextEntry()), entry.get() != NULL)
     {
-        wxString name = entry->GetName();    // access meta-data
-        txt >> data;                         // access data
+        // access meta-data
+        wxString name = entry->GetName();
+        // read 'zip' to access the entry's data
     }
 
 \end{verbatim}
@@ -103,19 +106,22 @@ much more efficient than transferring the data using Read() and Write()
 since it will copy them without decompressing and recompressing them.
 
 In general modifications are not possible without rewriting the archive,
-though it may be possible in some limited cases. Even then, rewriting
-the archive is usually a better choice since a failure can be handled
-without losing the whole archive.
+though it may be possible in some limited cases. Even then, rewriting the
+archive is usually a better choice since a failure can be handled without
+losing the whole
+archive. \helpref{wxTempFileOutputStream}{wxtempfileoutputstream} can
+be helpful to do this.
 
 For example to delete all entries matching the pattern "*.txt":
 
 \begin{verbatim}
-    wxFFileInputStream in(_T("in.zip"));
-    wxFFileOutputStream out(_T("out.zip"));
+    auto_ptr<wxFFileInputStream> in(new wxFFileInputStream(_T("test.zip")));
+    wxTempFileOutputStream out(_T("test.zip"));
 
-    wxZipInputStream inzip(in);
+    wxZipInputStream inzip(*in);
     wxZipOutputStream outzip(out);
-    wxZipEntryPtr entry;
+
+    auto_ptr<wxZipEntry> entry;
 
     // transfer any meta-data for the archive as a whole (the zip comment
     // in the case of zip)
@@ -127,7 +133,12 @@ For example to delete all entries matching the pattern "*.txt":
             if (!outzip.CopyEntry(entry.release(), inzip))
                 break;
 
-    bool success = inzip.Eof() && outzip.Close();
+    // close the input stream by releasing the pointer to it, do this
+    // before closing the output stream so that the file can be replaced
+    in.reset();
+
+    // you can check for success as follows
+    bool success = inzip.Eof() && outzip.Close() && out.Commit();
 
 \end{verbatim}
 
@@ -159,8 +170,7 @@ it is better to convert the local name to the archive's internal format
 and search for that:
 
 \begin{verbatim}
-    wxDEFINE_SCOPED_PTR_TYPE(wxZipEntry);
-    wxZipEntryPtr entry;
+    auto_ptr<wxZipEntry> entry;
 
     // convert the local name we are looking for into the internal format
     wxString name = wxZipEntry::GetInternalName(localname);
@@ -247,47 +257,76 @@ entry (e.g. filename)}
 
 In order to able to write generic code it's necessary to be able to create
 instances of the classes without knowing which archive type is being used.
-So there is a class factory for each archive type, derived from
- \helpref{wxArchiveClassFactory}{wxarchiveclassfactory}, which can create
+To allow this there is a class factory for each archive type, derived from
+ \helpref{wxArchiveClassFactory}{wxarchiveclassfactory}, that can create
 the other classes.
 
-For example, given {\it wxArchiveClassFactory* factory}:
+For example, given {\it wxArchiveClassFactory* factory}, streams and
+entries can be created like this:
 
 \begin{verbatim}
     // create streams without knowing their type
-    wxArchiveInputStreamPtr  inarc(factory->NewStream(in));
-    wxArchiveOutputStreamPtr outarc(factory->NewStream(out));
+    auto_ptr<wxArchiveInputStream> inarc(factory->NewStream(in));
+    auto_ptr<wxArchiveOutputStream> outarc(factory->NewStream(out));
 
     // create an empty entry object
-    wxArchiveEntryPtr        entry(factory->NewEntry());
+    auto_ptr<wxArchiveEntry> entry(factory->NewEntry());
 
 \end{verbatim}
 
-The class factory itself can either be created explicitly:
+For the factory itself, the static member
+ \helpref{wxArchiveClassFactory::Find()}{wxarchiveclassfactoryfind}.
+can be used to find a class factory that can handle a given file
+extension or mime type. For example, given {\it filename}:
 
 \begin{verbatim}
-    wxArchiveClassFactory *factory = new wxZipClassFactory;
+    const wxArchiveClassFactory *factory;
+    factory = wxArchiveClassFactory::Find(filename, wxSTREAM_FILEEXT);
+
+    if (factory)
+        stream = factory->NewStream(new wxFFileInputStream(filename));
 
 \end{verbatim}
 
-or using wxWidgets' \helpref{RTTI}{runtimeclassoverview}:
+{\it Find} does not give away ownership of the returned pointer, so it
+does not need to be deleted.
 
-\begin{verbatim}
-wxArchiveClassFactory *MakeFactory(const wxString& type)
-{
-    wxString name = _T("wx") + type.Left(1).Upper() +
-                    type.Mid(1).Lower() + _T("ClassFactory");
+There are similar class factories for the filter streams that handle the
+compression and decompression of a single stream, such as wxGzipInputStream.
+These can be found using
+ \helpref{wxFilterClassFactory::Find()}{wxfilterclassfactoryfind}.
 
-    wxObject *pObj = wxCreateDynamicObject(name);
-    wxArchiveClassFactory *pcf = wxDynamicCast(pObj, wxArchiveClassFactory);
+For example, to list the contents of archive {\it filename}:
 
-    if (!pcf) {
-        wxLogError(_T("can't handle '%s' archives"), type.c_str());
-        delete pObj;
-    }
+\begin{verbatim}
+    auto_ptr<wxInputStream> in(new wxFFileInputStream(filename));
 
-    return pcf;
-}
+    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}
 
@@ -369,9 +408,9 @@ required field before writing it with
  \helpref{CopyEntry()}{wxarchiveoutputstreamcopyentry}:
 
 \begin{verbatim}
-    wxArchiveInputStreamPtr  arc(factory->NewStream(in));
-    wxArchiveOutputStreamPtr outarc(factory->NewStream(out));
-    wxArchiveEntryPtr        entry;
+    auto_ptr<wxArchiveInputStream> arc(factory->NewStream(in));
+    auto_ptr<wxArchiveOutputStream> outarc(factory->NewStream(out));
+    auto_ptr<wxArchiveEntry> entry;
 
     outarc->CopyArchiveMetaData(*arc);
 
@@ -407,10 +446,10 @@ then \helpref{SetNotifier()}{wxarchiveentrynotifier} is called before
 CopyEntry():
 
 \begin{verbatim}
-    wxArchiveInputStreamPtr  arc(factory->NewStream(in));
-    wxArchiveOutputStreamPtr outarc(factory->NewStream(out));
-    wxArchiveEntryPtr        entry;
-    MyNotifier               notifier;
+    auto_ptr<wxArchiveInputStream> arc(factory->NewStream(in));
+    auto_ptr<wxArchiveOutputStream> outarc(factory->NewStream(out));
+    auto_ptr<wxArchiveEntry> entry;
+    MyNotifier notifier;
 
     outarc->CopyArchiveMetaData(*arc);