UNPKG

epubjs

Version:

Render ePub documents in the browser, across many devices

232 lines (225 loc) 33.1 kB
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data Compression</title><link rel="stylesheet" href="core.css" type="text/css"/><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"/></head><body><div class="sect1" title="Data Compression"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-12-SECT-4"/>Data Compression</h1></div></div></div><p>The <a id="I_indexterm12_id760639" class="indexterm"/><code class="literal">java.util.zip</code> package contains classes you can use for data compression in streams or files. The classes in the <code class="literal">java.util.zip</code> package support two widespread compression formats: GZIP and ZIP. In this section, we’ll talk about how to use these classes. We’ll also present two useful example programs that build on what you have learned in this chapter. After that, we’ll talk about a higher-level way to work with ZIP archives—as filesystems—introduced with Java 7.</p><div class="sect2" title="Archives and Compressed Data"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-12-SECT-4.1"/>Archives and Compressed Data</h2></div></div></div><p><a id="idx10677" class="indexterm"/> <a id="idx10689" class="indexterm"/>The <code class="literal">java.util.zip</code> package provides two filter streams for writing compressed data. The <a id="I_indexterm12_id760696" class="indexterm"/><code class="literal">GZIPOutputStream</code> is for writing data in GZIP compressed format. The <a id="I_indexterm12_id760707" class="indexterm"/><code class="literal">ZIPOutputStream</code> is for writing compressed ZIP archives, which can contain one or many files. To write compressed data in the GZIP format, simply wrap a <code class="literal">GZIPOutputStream</code> around an underlying stream and write to it. The following is a complete example that shows how to compress a file using the GZIP format, but the stream could just as well be sent over a network connection or to any other type of stream destination. Our <code class="literal">GZip</code> example is a command line utility that compresses a file.</p><a id="I_12_tt810"/><pre class="programlisting"> <code class="kn">import</code> <code class="nn">java.io.*</code><code class="o">;</code> <code class="kn">import</code> <code class="nn">java.util.zip.*</code><code class="o">;</code> <code class="kd">public</code> <code class="kd">class</code> <code class="nc">GZip</code> <code class="o">{</code> <code class="kd">public</code> <code class="kd">static</code> <code class="kt">int</code> <code class="n">sChunk</code> <code class="o">=</code> <code class="mi">8192</code><code class="o">;</code> <code class="kd">public</code> <code class="kd">static</code> <code class="kt">void</code> <code class="nf">main</code><code class="o">(</code><code class="n">String</code><code class="o">[]</code> <code class="n">args</code><code class="o">)</code> <code class="o">{</code> <code class="k">if</code> <code class="o">(</code><code class="n">args</code><code class="o">.</code><code class="na">length</code> <code class="o">!=</code> <code class="mi">1</code><code class="o">)</code> <code class="o">{</code> <code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code><code class="s">"Usage: GZip source"</code><code class="o">);</code> <code class="k">return</code><code class="o">;</code> <code class="o">}</code> <code class="c1">// create output stream</code> <code class="n">String</code> <code class="n">zipname</code> <code class="o">=</code> <code class="n">args</code><code class="o">[</code><code class="mi">0</code><code class="o">]</code> <code class="o">+</code> <code class="s">".gz"</code><code class="o">;</code> <code class="n">GZIPOutputStream</code> <code class="n">zipout</code><code class="o">;</code> <code class="k">try</code> <code class="o">{</code> <code class="n">FileOutputStream</code> <code class="n">out</code> <code class="o">=</code> <code class="k">new</code> <code class="n">FileOutputStream</code><code class="o">(</code><code class="n">zipname</code><code class="o">);</code> <code class="n">zipout</code> <code class="o">=</code> <code class="k">new</code> <code class="n">GZIPOutputStream</code><code class="o">(</code><code class="n">out</code><code class="o">);</code> <code class="o">}</code> <code class="k">catch</code> <code class="o">(</code><code class="n">IOException</code> <code class="n">e</code><code class="o">)</code> <code class="o">{</code> <code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code><code class="s">"Couldn't create "</code> <code class="o">+</code> <code class="n">zipname</code> <code class="o">+</code> <code class="s">"."</code><code class="o">);</code> <code class="k">return</code><code class="o">;</code> <code class="o">}</code> <code class="kt">byte</code><code class="o">[]</code> <code class="n">buffer</code> <code class="o">=</code> <code class="k">new</code> <code class="kt">byte</code><code class="o">[</code><code class="n">sChunk</code><code class="o">];</code> <code class="c1">// compress the file</code> <code class="k">try</code> <code class="o">{</code> <code class="n">FileInputStream</code> <code class="n">in</code> <code class="o">=</code> <code class="k">new</code> <code class="n">FileInputStream</code><code class="o">(</code><code class="n">args</code><code class="o">[</code><code class="mi">0</code><code class="o">]);</code> <code class="kt">int</code> <code class="n">length</code><code class="o">;</code> <code class="k">while</code> <code class="o">((</code><code class="n">length</code> <code class="o">=</code> <code class="n">in</code><code class="o">.</code><code class="na">read</code><code class="o">(</code><code class="n">buffer</code><code class="o">,</code> <code class="mi">0</code><code class="o">,</code> <code class="n">sChunk</code><code class="o">))</code> <code class="o">!=</code> <code class="o">-</code><code class="mi">1</code><code class="o">)</code> <code class="n">zipout</code><code class="o">.</code><code class="na">write</code><code class="o">(</code><code class="n">buffer</code><code class="o">,</code> <code class="mi">0</code><code class="o">,</code> <code class="n">length</code><code class="o">);</code> <code class="n">in</code><code class="o">.</code><code class="na">close</code><code class="o">();</code> <code class="o">}</code> <code class="k">catch</code> <code class="o">(</code><code class="n">IOException</code> <code class="n">e</code><code class="o">)</code> <code class="o">{</code> <code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code><code class="s">"Couldn't compress "</code> <code class="o">+</code> <code class="n">args</code><code class="o">[</code><code class="mi">0</code><code class="o">]</code> <code class="o">+</code> <code class="s">"."</code><code class="o">);</code> <code class="o">}</code> <code class="k">try</code> <code class="o">{</code> <code class="n">zipout</code><code class="o">.</code><code class="na">close</code><code class="o">();</code> <code class="o">}</code> <code class="k">catch</code> <code class="o">(</code><code class="n">IOException</code> <code class="n">e</code><code class="o">)</code> <code class="o">{}</code> <code class="o">}</code> <code class="o">}</code></pre><p>First, we check to make sure we have a command-line argument representing a filename. We then construct a <code class="literal">GZIPOutputStream</code> wrapped around a <code class="literal">FileOutputStream</code> representing the given filename, with the <span class="emphasis"><em>.gz</em></span> suffix appended. With this in place, we open the source file. We read chunks of data and write them into the <code class="literal">GZIPOutputStream</code>. Finally, we clean up by closing our open streams.</p><div class="sect3" title="Zip archives"><div class="titlepage"><div><div><h3 class="title"><a id="id1267505"/>Zip archives</h3></div></div></div><p><a id="idx10759" class="indexterm"/>While GZIP is simple compression format for a stream or file, a ZIP archive is a file that is actually a collection of files, some (or all) of which may be compressed. Writing data to a ZIP archive file is a little more involved than simply wrapping a stream, but not difficult. Each item in the ZIP file is represented by a <a id="I_indexterm12_id760794" class="indexterm"/><code class="literal">ZipEntry</code> object. When writing to a <a id="I_indexterm12_id760804" class="indexterm"/><code class="literal">ZipOutputStream</code>, you’ll need to call <a id="I_indexterm12_id760815" class="indexterm"/><code class="literal">putNextEntry()</code> before writing the data for each item. The following example shows how to create a <code class="literal">ZipOutputStream</code>. You’ll notice that it starts out with a stream wrapper just like it did when creating a <code class="literal">GZIPOutputStream</code>:</p><a id="I_12_tt811"/><pre class="programlisting"> <code class="n">ZipOutputStream</code> <code class="n">zipout</code><code class="o">;</code> <code class="k">try</code> <code class="o">{</code> <code class="n">FileOutputStream</code> <code class="n">out</code> <code class="o">=</code> <code class="k">new</code> <code class="n">FileOutputStream</code><code class="o">(</code><code class="s">"archive.zip"</code><code class="o">);</code> <code class="n">zipout</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ZipOutputStream</code><code class="o">(</code><code class="n">out</code><code class="o">);</code> <code class="o">}</code> <code class="k">catch</code> <code class="o">(</code><code class="n">IOException</code> <code class="n">e</code><code class="o">)</code> <code class="o">{}</code></pre><p>Let’s say we have two files we want to write into this archive. Before we begin writing, we need to call <code class="literal">putNextEntry()</code> to set the name of the file within the archive and initialize the stream to the correct position for it. Here we create a simple ZipEntry with just a file name. You can set other ZIP format specific fields in <code class="literal">ZipEntry</code>, but most of the time, you won’t need to bother with them.<a id="I_indexterm12_id760867" class="indexterm"/><a id="I_indexterm12_id760874" class="indexterm"/><a id="I_indexterm12_id760882" class="indexterm"/></p><a id="I_12_tt812"/><pre class="programlisting"> <code class="k">try</code> <code class="o">{</code> <code class="n">ZipEntry</code> <code class="n">entry</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ZipEntry</code><code class="o">(</code><code class="s">"first.dat"</code><code class="o">);</code> <code class="n">zipout</code><code class="o">.</code><code class="na">putNextEntry</code><code class="o">(</code><code class="n">entry</code><code class="o">);</code> <code class="n">zipout</code><code class="o">.</code><code class="na">write</code><code class="o">(</code> <code class="o">...</code> <code class="o">)</code> <code class="c1">// Write data for first file</code> <code class="n">ZipEntry</code> <code class="n">entry</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ZipEntry</code><code class="o">(</code><code class="s">"second.dat"</code><code class="o">);</code> <code class="n">zipout</code><code class="o">.</code><code class="na">putNextEntry</code><code class="o">(</code><code class="n">entry</code><code class="o">);</code> <code class="n">zipout</code><code class="o">.</code><code class="na">write</code><code class="o">(</code> <code class="o">...</code> <code class="o">)</code> <code class="c1">// Write data for second file</code> <code class="o">.</code> <code class="o">.</code> <code class="o">.</code> <code class="n">zipout</code><code class="o">.</code><code class="na">close</code><code class="o">();</code> <code class="o">}</code> <code class="k">catch</code> <code class="o">(</code><code class="n">IOException</code> <code class="n">e</code><code class="o">)</code> <code class="o">{}</code></pre></div></div><div class="sect2" title="Decompressing Data"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-12-SECT-4.2"/>Decompressing Data</h2></div></div></div><p><a id="idx10690" class="indexterm"/> <a id="idx10705" class="indexterm"/>To decompress data in the GZIP format, simply wrap a <a id="I_indexterm12_id760936" class="indexterm"/><code class="literal">GZIPInputStream</code> around an underlying <code class="literal">FileInputStream</code> and read from it. The following example complements our earlier <code class="literal">GZip</code> example and shows how to decompress a GZIP file:</p><a id="I_12_tt813"/><pre class="programlisting"> <code class="kn">import</code> <code class="nn">java.io.*</code><code class="o">;</code> <code class="kn">import</code> <code class="nn">java.util.zip.*</code><code class="o">;</code> <code class="kd">public</code> <code class="kd">class</code> <code class="nc">GUnzip</code> <code class="o">{</code> <code class="kd">public</code> <code class="kd">static</code> <code class="kt">int</code> <code class="n">sChunk</code> <code class="o">=</code> <code class="mi">8192</code><code class="o">;</code> <code class="kd">public</code> <code class="kd">static</code> <code class="kt">void</code> <code class="nf">main</code><code class="o">(</code><code class="n">String</code><code class="o">[]</code> <code class="n">args</code><code class="o">)</code> <code class="o">{</code> <code class="k">if</code> <code class="o">(</code><code class="n">args</code><code class="o">.</code><code class="na">length</code> <code class="o">!=</code> <code class="mi">1</code><code class="o">)</code> <code class="o">{</code> <code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code><code class="s">"Usage: GUnzip source"</code><code class="o">);</code> <code class="k">return</code><code class="o">;</code> <code class="o">}</code> <code class="c1">// create input stream</code> <code class="n">String</code> <code class="n">zipname</code><code class="o">,</code> <code class="n">source</code><code class="o">;</code> <code class="k">if</code> <code class="o">(</code><code class="n">args</code><code class="o">[</code><code class="mi">0</code><code class="o">].</code><code class="na">endsWith</code><code class="o">(</code><code class="s">".gz"</code><code class="o">))</code> <code class="o">{</code> <code class="n">zipname</code> <code class="o">=</code> <code class="n">args</code><code class="o">[</code><code class="mi">0</code><code class="o">];</code> <code class="n">source</code> <code class="o">=</code> <code class="n">args</code><code class="o">[</code><code class="mi">0</code><code class="o">].</code><code class="na">substring</code><code class="o">(</code><code class="mi">0</code><code class="o">,</code> <code class="n">args</code><code class="o">[</code><code class="mi">0</code><code class="o">].</code><code class="na">length</code><code class="o">()</code> <code class="o">-</code> <code class="mi">3</code><code class="o">);</code> <code class="o">}</code> <code class="k">else</code> <code class="o">{</code> <code class="n">zipname</code> <code class="o">=</code> <code class="n">args</code><code class="o">[</code><code class="mi">0</code><code class="o">]</code> <code class="o">+</code> <code class="s">".gz"</code><code class="o">;</code> <code class="n">source</code> <code class="o">=</code> <code class="n">args</code><code class="o">[</code><code class="mi">0</code><code class="o">];</code> <code class="o">}</code> <code class="n">GZIPInputStream</code> <code class="n">zipin</code><code class="o">;</code> <code class="k">try</code> <code class="o">{</code> <code class="n">FileInputStream</code> <code class="n">in</code> <code class="o">=</code> <code class="k">new</code> <code class="n">FileInputStream</code><code class="o">(</code><code class="n">zipname</code><code class="o">);</code> <code class="n">zipin</code> <code class="o">=</code> <code class="k">new</code> <code class="n">GZIPInputStream</code><code class="o">(</code><code class="n">in</code><code class="o">);</code> <code class="o">}</code> <code class="k">catch</code> <code class="o">(</code><code class="n">IOException</code> <code class="n">e</code><code class="o">)</code> <code class="o">{</code> <code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code><code class="s">"Couldn't open "</code> <code class="o">+</code> <code class="n">zipname</code> <code class="o">+</code> <code class="s">"."</code><code class="o">);</code> <code class="k">return</code><code class="o">;</code> <code class="o">}</code> <code class="kt">byte</code><code class="o">[]</code> <code class="n">buffer</code> <code class="o">=</code> <code class="k">new</code> <code class="kt">byte</code><code class="o">[</code><code class="n">sChunk</code><code class="o">];</code> <code class="c1">// decompress the file</code> <code class="k">try</code> <code class="o">{</code> <code class="n">FileOutputStream</code> <code class="n">out</code> <code class="o">=</code> <code class="k">new</code> <code class="n">FileOutputStream</code><code class="o">(</code><code class="n">source</code><code class="o">);</code> <code class="kt">int</code> <code class="n">length</code><code class="o">;</code> <code class="k">while</code> <code class="o">((</code><code class="n">length</code> <code class="o">=</code> <code class="n">zipin</code><code class="o">.</code><code class="na">read</code><code class="o">(</code><code class="n">buffer</code><code class="o">,</code> <code class="mi">0</code><code class="o">,</code> <code class="n">sChunk</code><code class="o">))</code> <code class="o">!=</code> <code class="o">-</code><code class="mi">1</code><code class="o">)</code> <code class="n">out</code><code class="o">.</code><code class="na">write</code><code class="o">(</code><code class="n">buffer</code><code class="o">,</code> <code class="mi">0</code><code class="o">,</code> <code class="n">length</code><code class="o">);</code> <code class="n">out</code><code class="o">.</code><code class="na">close</code><code class="o">();</code> <code class="o">}</code> <code class="k">catch</code> <code class="o">(</code><code class="n">IOException</code> <code class="n">e</code><code class="o">)</code> <code class="o">{</code> <code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code><code class="s">"Couldn't decompress "</code> <code class="o">+</code> <code class="n">args</code><code class="o">[</code><code class="mi">0</code><code class="o">]</code> <code class="o">+</code> <code class="s">"."</code><code class="o">);</code> <code class="o">}</code> <code class="k">try</code> <code class="o">{</code> <code class="n">zipin</code><code class="o">.</code><code class="na">close</code><code class="o">();</code> <code class="o">}</code> <code class="k">catch</code> <code class="o">(</code><code class="n">IOException</code> <code class="n">e</code><code class="o">)</code> <code class="o">{}</code> <code class="o">}</code> <code class="o">}</code></pre><p>First, we check to make sure we have a command-line argument representing a filename. If the argument ends with <span class="emphasis"><em>.gz</em></span>, we figure out what the filename for the uncompressed file should be. Otherwise, we use the given argument and assume the compressed file has the <a id="I_indexterm12_id760986" class="indexterm"/><span class="emphasis"><em>.gz</em></span> suffix. Then we construct a <code class="literal">GZIPInputStream</code> wrapped around a <code class="literal">FileInputStream</code> that represents the compressed file. With this in place, we open the target file. We read chunks of data from the <code class="literal">GZIPInputStream</code> and write them into the target file. Finally, we clean up by closing our open streams.</p><p>Reading a ZIP archive is also the mirror of writing. When reading from a <a id="I_indexterm12_id761018" class="indexterm"/><code class="literal">ZipInputStream</code>, you should call <a id="I_indexterm12_id761028" class="indexterm"/><code class="literal">getNextEntry()</code> before reading each item. When <code class="literal">getNextEntry()</code> returns <code class="literal">null</code>, there are no more items to read. The following example shows how to create a <code class="literal">ZipInputStream</code>:</p><a id="I_12_tt814"/><pre class="programlisting"> <code class="n">ZipInputStream</code> <code class="n">zipin</code><code class="o">;</code> <code class="k">try</code> <code class="o">{</code> <code class="n">FileInputStream</code> <code class="n">in</code> <code class="o">=</code> <code class="k">new</code> <code class="n">FileInputStream</code><code class="o">(</code><code class="s">"archive.zip"</code><code class="o">);</code> <code class="n">zipin</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ZipInputStream</code><code class="o">(</code><code class="n">in</code><code class="o">);</code> <code class="o">}</code> <code class="k">catch</code> <code class="o">(</code><code class="n">IOException</code> <code class="n">e</code><code class="o">)</code> <code class="o">{}</code></pre><p>Suppose we want to read two files from this archive. Before we begin reading, we need to call <code class="literal">getNextEntry()</code>. At the very least, the entry gives us a name of the item we are reading from the archive:</p><a id="I_12_tt815"/><pre class="programlisting"> <code class="k">try</code> <code class="o">{</code> <code class="n">ZipEntry</code> <code class="n">first</code> <code class="o">=</code> <code class="n">zipin</code><code class="o">.</code><code class="na">getNextEntry</code><code class="o">();</code> <code class="n">zipin</code><code class="o">.</code><code class="na">read</code><code class="o">(</code> <code class="o">...</code> <code class="o">)</code> <code class="c1">// Read the file data</code> <code class="o">}</code> <code class="k">catch</code> <code class="o">(</code><code class="n">IOException</code> <code class="n">e</code><code class="o">)</code> <code class="o">{}</code></pre><p>Now, you can read the contents of the first item in the archive. When you <span><span>come to</span> the</span> end of the item, the <code class="literal">read()</code> method returns <code class="literal">-1</code>. At this point, you can call <code class="literal">getNext</code><code class="literal">Entry()</code> again to read the second item from the archive. If you call <code class="literal">getNextEntry()</code> and it returns <code class="literal">null</code>, there are no more items and you have reached the end of the archive.<a id="I_indexterm12_id761129" class="indexterm"/><a id="I_indexterm12_id761136" class="indexterm"/></p></div><div class="sect2" title="Zip Archive As a Filesystem"><div class="titlepage"><div><div><h2 class="title"><a id="id718623"/>Zip Archive As a Filesystem</h2></div></div></div><p><a id="idx10691" class="indexterm"/> <a id="idx10706" class="indexterm"/>One of the benefits of the new <code class="literal">java.nio.file</code> package introduce with Java 7 is the ability to implement custom filesystems in Java. (We talked about the File API for the NIO file package earlier in this chapter and we’ll return to the more general NIO facilities in the next section.) Java 7 ships with one such custom filesystem implementation bundled within it: the Zip Filesystem Provider.<sup>[<a id="id718891" href="#ftn.id718891" class="footnote">35</a>]</sup> Using the Zip Filesystem Provider, we can open a ZIP archive and treat it like a filesystem: reading, writing, copying, and renaming files using all of the standard <code class="literal">java.nio.file</code> APIs, except that all of these operations happen inside the ZIP archive file instead of on the host computer filesystem (as you might otherwise expect).</p><p>The key to making this possible is that the NIO File API starts with a <code class="literal">FileSystem</code> abstraction that serves as a factory for <code class="literal">Path</code> objects. In our previous discussion of the NIO File API we always simply asked for the default filesystem using <code class="literal">Filesystems.getDefault()</code>. This time, we are going to target a particular custom filesystem type and destination by constructing a special URI for our ZIP archive. (As we’ll discuss in the networking chapters, a URI is kind of like a URL except that it can be more abstract).</p><a id="I_programlisting12_id761231"/><pre class="programlisting"> <code class="c1">// Construct the URI pointing to the ZIP archive</code> <code class="n">URI</code> <code class="n">zipURI</code> <code class="o">=</code> <code class="n">URI</code><code class="o">.</code><code class="na">create</code><code class="o">(</code><code class="s">"jar:file:/Users/pat/tmp/MyArchive.zip"</code><code class="o">);</code> <code class="c1">// Open or create it and write a file</code> <code class="n">Map</code><code class="o">&lt;</code><code class="n">String</code><code class="o">,</code> <code class="n">String</code><code class="o">&gt;</code> <code class="n">env</code> <code class="o">=</code> <code class="k">new</code> <code class="n">HashMap</code><code class="o">&lt;&gt;();</code> <code class="n">env</code><code class="o">.</code><code class="na">put</code><code class="o">(</code><code class="s">"create"</code><code class="o">,</code> <code class="s">"true"</code><code class="o">);</code> <code class="k">try</code> <code class="o">(</code> <code class="n">FileSystem</code> <code class="n">zipfs</code> <code class="o">=</code> <code class="n">FileSystems</code><code class="o">.</code><code class="na">newFileSystem</code><code class="o">(</code> <code class="n">zipURI</code><code class="o">,</code> <code class="n">env</code> <code class="o">)</code> <code class="o">)</code> <code class="o">{</code> <code class="n">Path</code> <code class="n">path</code> <code class="o">=</code> <code class="n">zipfs</code><code class="o">.</code><code class="na">getPath</code><code class="o">(</code><code class="s">"/README.txt"</code><code class="o">);</code> <code class="n">OutputStream</code> <code class="n">out</code> <code class="o">=</code> <code class="n">Files</code><code class="o">.</code><code class="na">newOutputStream</code><code class="o">(</code> <code class="n">path</code> <code class="o">);</code> <code class="k">try</code> <code class="o">(</code> <code class="n">PrintWriter</code> <code class="n">pw</code> <code class="o">=</code> <code class="k">new</code> <code class="n">PrintWriter</code><code class="o">(</code> <code class="k">new</code> <code class="nf">OutputStreamWriter</code><code class="o">(</code> <code class="n">out</code> <code class="o">)</code> <code class="o">)</code> <code class="o">)</code> <code class="o">{</code> <code class="n">pw</code><code class="o">.</code><code class="na">println</code><code class="o">(</code><code class="s">"Hello World!"</code><code class="o">);</code> <code class="o">}</code> <code class="o">}</code></pre><p>In this snippet, we constructed a URI for our ZIP archive using the <code class="literal">URI</code><code class="literal">create()</code> method and the special <span class="emphasis"><em>jar:file:</em></span> prefix. (The Java JAR format is really just the ZIP format with some additional conventions.) We then used that URI with the <code class="literal">Filesystems newFileSystem()</code> method to create the right kind of filesystem reference for us. The <code class="literal">FileSystem</code> it returns will perform all of its operations on entries within the ZIP, but otherwise will behave just like we’ve seen previously. The other argument to the <a id="I_indexterm12_id761283" class="indexterm"/><code class="literal">newFileSystem()</code> method is a <code class="literal">Map</code> containing string properties that are specific to the provider. In this case, we pass in the value “create” as “true,” indicating that we want the ZIP filesystem provider to create the archive if it does not already exist. In order to know what properties can be passed, you’ll have to consult the documentation for the particular filesystem provider.</p><p>In our preceding snippet, we then create a <code class="literal">Path</code> for a file <span class="emphasis"><em>/README.txt</em></span> at the root folder of the filesystem and write a string to it. Because we are using <code class="literal">try</code>-with-resources clauses to encapsulate opening the filesystem and writing to the file, the resources will be automatically closed for us when the operation is complete.</p><p>Other operations proceed just as with “normal” files. For example, we can move a file by creating a path for the existing file and a path for the new location and then using the standard <code class="literal">Files move()</code> method.<a id="I_indexterm12_id761335" class="indexterm"/><a id="I_indexterm12_id761342" class="indexterm"/></p><a id="I_programlisting12_id761350"/><pre class="programlisting"> <code class="c1">// Move the file</code> <code class="k">try</code> <code class="o">(</code> <code class="n">FileSystem</code> <code class="n">zipfs</code> <code class="o">=</code> <code class="n">FileSystems</code><code class="o">.</code><code class="na">newFileSystem</code><code class="o">(</code> <code class="n">fsURI</code><code class="o">,</code> <code class="n">env</code> <code class="o">)</code> <code class="o">)</code> <code class="o">{</code> <code class="n">Path</code> <code class="n">path</code> <code class="o">=</code> <code class="n">zipfs</code><code class="o">.</code><code class="na">getPath</code><code class="o">(</code><code class="s">"/README.txt"</code><code class="o">);</code> <code class="n">Path</code> <code class="n">toPath</code> <code class="o">=</code> <code class="n">zipfs</code><code class="o">.</code><code class="na">getPath</code><code class="o">(</code><code class="s">"/README2.txt"</code><code class="o">);</code> <code class="n">Files</code><code class="o">.</code><code class="na">move</code><code class="o">(</code> <code class="n">path</code><code class="o">,</code> <code class="n">toPath</code> <code class="o">);</code> <code class="o">}</code></pre></div><div class="footnotes"><br/><hr/><div class="footnote"><p><sup>[<a id="ftn.id718891" href="#id718891" class="para">35</a>] </sup>The Zip Filesystem Provider is also supplied as an example along with sample source code even though it’s unclear if Oracle intends it to be a standard. But at the time of this writing, it is bundled with the JDK and JRE of Java 7 on all platforms.</p></div></div></div></body></html>