arc.tex
来自「Wxpython Implemented on Windows CE, Sou」· TEX 代码 · 共 479 行 · 第 1/2 页
TEX
479 行
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Name: arc.tex
%% Purpose: Overview of the archive classes
%% Author: M.J.Wetherell
%% RCS-ID: $Id: arc.tex,v 1.4 2005/07/04 12:21:35 MW Exp $
%% Copyright: 2004 M.J.Wetherell
%% License: wxWindows license
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\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. wxTar classes are under
development at \urlref{wxCode}{http://wxcode.sf.net}.
For each archive type, there are the following classes (using zip here
as an example):
\begin{twocollist}\twocolwidtha{4cm}
\twocolitem{\helpref{wxZipInputStream}{wxzipinputstream}}{Input stream}
\twocolitem{\helpref{wxZipOutputStream}{wxzipoutputstream}}{Output stream}
\twocolitem{\helpref{wxZipEntry}{wxzipentry}}{Holds the meta-data for an
entry (e.g. filename, timestamp, etc.)}
\end{twocollist}
There are also abstract wxArchive classes that can be used to write code
that can handle any of the archive types,
see '\helpref{Generic archive programming}{wxarcgeneric}'.
Also see \helpref{wxFileSystem}{fs} for a higher level interface that
can handle archive files in a generic way.
The classes are designed to handle archives on both seekable streams such
as disk files, or non-seekable streams such as pipes and sockets
(see '\helpref{Archives on non-seekable streams}{wxarcnoseek}').
\wxheading{See also}
\helpref{wxFileSystem}{fs}
\subsection{Creating an archive}\label{wxarccreate}
\helpref{Archive formats such as zip}{wxarc}
Call \helpref{PutNextEntry()}{wxarchiveoutputstreamputnextentry} to
create each new entry in the archive, then write the entry's data.
Another call to PutNextEntry() closes the current entry and begins the next.
For example:
\begin{verbatim}
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.txt\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 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}
// 'smart pointer' type created with wxDEFINE_SCOPED_PTR_TYPE
wxZipEntryPtr entry;
wxFFileInputStream in(_T("test.zip"));
wxZipInputStream zip(in);
while (entry.reset(zip.GetNextEntry()), entry.get() != NULL)
{
// access meta-data
wxString name = entry->GetName();
// read 'zip' to access the entry's data
}
\end{verbatim}
The \helpref{smart pointer}{wxscopedptr} type {\em wxZipEntryPtr}
can be created like this:
\begin{verbatim}
#include <wx/ptr_scpd.h>
wxDEFINE_SCOPED_PTR_TYPE(wxZipEntry);
\end{verbatim}
\subsection{Modifying an archive}\label{wxarcmodify}
\helpref{Archive formats such as zip}{wxarc}
To modify an existing archive, write a new copy of the archive to a new file,
making any necessary changes along the way and transferring any unchanged
entries using \helpref{CopyEntry()}{wxarchiveoutputstreamcopyentry}.
For archive types which compress entry data, CopyEntry() is likely to be
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. \helpref{wxTempFileOutputStream}{wxtempfileoutputstream} can
be helpful to do this.
For example to delete all entries matching the pattern "*.txt":
\begin{verbatim}
wxFFileInputStreamPtr in(new wxFFileInputStream(_T("test.zip")));
wxTempFileOutputStream out(_T("test.zip"));
wxZipInputStream inzip(*in);
wxZipOutputStream outzip(out);
// 'smart pointer' type created with wxDEFINE_SCOPED_PTR_TYPE
wxZipEntryPtr entry;
// transfer any meta-data for the archive as a whole (the zip comment
// in the case of zip)
outzip.CopyArchiveMetaData(inzip);
// call CopyEntry for each entry except those matching the pattern
while (entry.reset(inzip.GetNextEntry()), entry.get() != NULL)
if (!entry->GetName().Matches(_T("*.txt")))
if (!outzip.CopyEntry(entry.release(), inzip))
break;
// 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}
The \helpref{smart pointer}{wxscopedptr} types {\em wxZipEntryPtr}
and {\em wxFFileInputStreamPtr} can be created like this:
\begin{verbatim}
#include <wx/ptr_scpd.h>
wxDEFINE_SCOPED_PTR_TYPE(wxZipEntry);
wxDEFINE_SCOPED_PTR_TYPE(wxFFileInputStream);
\end{verbatim}
\subsection{Looking up an archive entry by name}\label{wxarcbyname}
\helpref{Archive formats such as zip}{wxarc}
Also see \helpref{wxFileSystem}{fs} for a higher level interface that is
more convenient for accessing archive entries by name.
To open just one entry in an archive, the most efficient way is
to simply search for it linearly by calling
\helpref{GetNextEntry()}{wxarchiveinputstreamgetnextentry} until the
required entry is found. This works both for archives on seekable and
non-seekable streams.
The format of filenames in the archive is likely to be different
from the local filename format. For example zips and tars use
unix style names, with forward slashes as the path separator,
and absolute paths are not allowed. So if on Windows the file
"C:$\backslash$MYDIR$\backslash$MYFILE.TXT" is stored, then when reading
the entry back \helpref{GetName()}{wxarchiveentryname} will return
"MYDIR$\backslash$MYFILE.TXT". The conversion into the internal format
and back has lost some information.
So to avoid ambiguity when searching for an entry matching a local name,
it is better to convert the local name to the archive's internal format
and search for that:
\begin{verbatim}
// 'smart pointer' type created with wxDEFINE_SCOPED_PTR_TYPE
wxZipEntryPtr entry;
// convert the local name we are looking for into the internal format
wxString name = wxZipEntry::GetInternalName(localname);
// open the zip
wxFFileInputStream in(_T("test.zip"));
wxZipInputStream zip(in);
// call GetNextEntry() until the required internal name is found
do {
entry.reset(zip.GetNextEntry());
}
while (entry.get() != NULL && entry->GetInternalName() != name);
if (entry.get() != NULL) {
// read the entry's data...
}
\end{verbatim}
To access several entries randomly, it is most efficient to transfer the
entire catalogue of entries to a container such as a std::map or a
\helpref{wxHashMap}{wxhashmap} then entries looked up by name can be
opened using the \helpref{OpenEntry()}{wxarchiveinputstreamopenentry} method.
\begin{verbatim}
WX_DECLARE_STRING_HASH_MAP(wxZipEntry*, ZipCatalog);
ZipCatalog::iterator it;
wxZipEntry *entry;
ZipCatalog cat;
// open the zip
wxFFileInputStream in(_T("test.zip"));
wxZipInputStream zip(in);
// load the zip catalog
while ((entry = zip.GetNextEntry()) != NULL) {
wxZipEntry*& current = cat[entry->GetInternalName()];
// some archive formats can have multiple entries with the same name
// (e.g. tar) though it is an error in the case of zip
delete current;
current = entry;
}
// open an entry by name
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?