You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by bo...@apache.org on 2018/05/07 19:15:00 UTC
commons-compress git commit: provide some more detailed examples
Repository: commons-compress
Updated Branches:
refs/heads/master 81398f69f -> 2b8171bd3
provide some more detailed examples
Project: http://git-wip-us.apache.org/repos/asf/commons-compress/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-compress/commit/2b8171bd
Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/2b8171bd
Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/2b8171bd
Branch: refs/heads/master
Commit: 2b8171bd351e0db50c80665155b90702fdb6855f
Parents: 81398f6
Author: Stefan Bodewig <bo...@apache.org>
Authored: Mon May 7 21:14:22 2018 +0200
Committer: Stefan Bodewig <bo...@apache.org>
Committed: Mon May 7 21:14:22 2018 +0200
----------------------------------------------------------------------
src/site/xdoc/examples.xml | 154 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 154 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/commons-compress/blob/2b8171bd/src/site/xdoc/examples.xml
----------------------------------------------------------------------
diff --git a/src/site/xdoc/examples.xml b/src/site/xdoc/examples.xml
index 3f841b7..ec6ced7 100644
--- a/src/site/xdoc/examples.xml
+++ b/src/site/xdoc/examples.xml
@@ -119,6 +119,160 @@ CompressorInputStream input = new CompressorStreamFactory()
</subsection>
+ <subsection name="Entry Names">
+ <p>All archive formats provide meta data about the individual
+ archive entries via instances of <code>ArchiveEntry</code> (or
+ rather subclasses of it). When reading from an archive the
+ information provided the <code>getName</code> method is the
+ raw name as stored inside of the archive. There is no
+ guarantee the name represents a relative file name or even a
+ valid file name on your target operating system at all. You
+ should double check the outcome when you try to create file
+ names from entry names.</p>
+ </subsection>
+
+ <subsection name="Common Extraction Logic">
+ <p>Apart from 7z all formats provide a subclass of
+ <code>ArchiveInputStream</code> that can be used to create an
+ archive. For 7z <code>SevenZFile</code> provides a similar API
+ that does not represent a stream as our implementation
+ requires random access to the input and cannot be used for
+ general streams. The ZIP implementation can benefit a lot from
+ random access as well, see the <a
+ href="zip.html#ZipArchiveInputStream%20vs$20ZipFile">zip
+ page</a> for details.</p>
+
+ <p>Assuming you want to extract an archive to a target
+ directory you'd call <code>getNextEntry</code>, verify the
+ entry can be read, construct a sane file name from the entry's
+ name, create a <codee>File</codee> and write all contents to
+ it - here <code>IOUtils.copy</code> may come handy. You do so
+ for every entry until <code>getNextEntry</code> returns
+ <code>null</code>.</p>
+
+ <p>A skeleton might look like:</p>
+
+ <source><![CDATA[
+File targetDir = ...
+try (ArchiveInputStream i = ... create the stream for your format, use buffering...) {
+ ArchiveEntry entry = null;
+ while ((entry = i.getNextEntry()) != null) {
+ if (!i.canReadEntryData(entry)) {
+ // log something?
+ continue;
+ }
+ String name = fileName(targetDir, entry);
+ File f = new File(name);
+ if (entry.isDirectory()) {
+ f.mkdirs();
+ } else {
+ f.getParentFile().mkdirs();
+ try (OutputStream o = Files.newOutputStream(f.toPath())) {
+ IOUtils.copy(i, o);
+ }
+ }
+ }
+}
+]]></source>
+
+ <p>where the hypothetical <code>fileName</code> method is
+ written by you and provides the absolute name for the file
+ that is going to be written on disk. Here you should perform
+ checks that ensure the resulting file name actually is a valid
+ file name on your operating system or belongs to a file inside
+ of <code>targetDir</code> when using the entry's name as
+ input.</p>
+
+ <p>If you want to combine an archive format with a compression
+ format - like when reading a "tar.gz" file - you wrap the
+ <code>ArchiveInputStream</code> around
+ <code>CompressorInputStream</code> for example:</p>
+
+ <source><![CDATA[
+try (InputStream fi = new Files.newInputStream(Paths.get("my.tar.gz"));
+ InputStream bi = new BufferedInputStream(fi);
+ InputStream gzi = new GzipCompressorInputStream(bi);
+ ArchiveInputStream o = new TarArchiveInputStream(gzi)) {
+}
+]]></source>
+
+ </subsection>
+
+ <subsection name="Common Archival Logic">
+ <p>Apart from 7z all formats that support writing provide a
+ subclass of <code>ArchiveOutputStream</code> that can be used
+ to create an archive. For 7z <code>SevenZOutputFile</code>
+ provides a similar API that does not represent a stream as our
+ implementation requires random access to the output and cannot
+ be used for general streams. The
+ <code>ZipArchiveOutputStream</code> class will benefit from
+ random access as well but can be used for non-seekable streams
+ - but not all features will be available and the archive size
+ might be slightly bigger, see <a
+ href="zip.html#ZipArchiveOutputStream">the zip page</a> for
+ details.</p>
+
+ <p>Assuming you want to add a collection of files to an
+ archive, you can first use <code>createArchiveEntry</code> for
+ each file. In general this will set a few flags (usually the
+ last modified time, the size and the information whether this
+ is a file or directory) based on the <code>File</code>
+ instance. Alternatively you can create the
+ <code>ArchiveEntry</code> subclass corresponding to your
+ format directly. Often you may want to set additional flags
+ like file permissions or owner information before adding the
+ entry to the archive.</p>
+
+ <p>Next you use <code>putArchiveEntry</code> in order to add
+ the entry and then start using <code>write</code> to add the
+ content of the entry - here <code>IOUtils.copy</code> may
+ come handy. Finally you invoke
+ <code>closeArchiveEntry</code> once you've written all content
+ and before you add the next entry.</p>
+
+ <p>Once all entries have been added you'd invoke
+ <code>finish</code> and finally <code>close</code> the
+ stream.</p>
+
+ <p>A skeleton might look like:</p>
+
+ <source><![CDATA[
+Collection<File> filesToArchive = ...
+try (ArchiveOutputStream o = ... create the stream for your format ...) {
+ for (File f : filesToArchive) {
+ // maybe skip directories for formats like AR that don't store directories
+ ArchiveEntry entry = o.createArchiveEntry(f, entryName(f));
+ // potentially add more flags to entry
+ o.putArchiveEntry(entry);
+ if (f.isFile()) {
+ try (InputStream i = Files.newInputStream(f.toPath())) {
+ IOUtils.copy(i, o);
+ }
+ }
+ o.closeArchiveEntry();
+ }
+ out.finish();
+}
+]]></source>
+
+ <p>where the hypothetical <code>entryName</code> method is
+ written by you and provides the name for the entry as it is
+ going to be written to the archive.</p>
+
+ <p>If you want to combine an archive format with a compression
+ format - like when creating a "tar.gz" file - you wrap the
+ <code>ArchiveOutputStream</code> around a
+ <code>CompressorOutputStream</code> for example:</p>
+
+ <source><![CDATA[
+try (OutputStream fo = Files.newOutputStream(Paths.get("my.tar.gz"));
+ OutputStream gzo = new GzipCompressorOutputStream(fo);
+ ArchiveOutputStream o = new TarArchiveOutputStream(gzo)) {
+}
+]]></source>
+
+ </subsection>
+
<subsection name="7z">
<p>Note that Commons Compress currently only supports a subset