[Java] The ZIP filesystem provider in JDK7

NIO2デモプロジェクトの目的は以下の通りです。
  • NIOファイルシステムプロバイダを使ってカスタムファイルシステム、ZIPファイルシステムをデプロイする方法を紹介する
  • NIO2ファイルシステムAPIを使ってZip/Jarファイルに簡単にアクセスできることをご紹介する
Package java.nio.file
http://download.java.net/jdk7/docs/api/index.html?java/nio/file/package-summary.html

.ZIP File Format Specification
http://www.pkware.com/documents/casestudies/APPNOTE.TXT

将来のjava.util.zip.ZipFileクラスのアップデートのために用意されたコードをたまたま持っていたので、NIO2ファイルシステムプロバイダSPIでラップしてzipfs.jarとして固め、<JDK>/demo/nio/zipfsディレクトリに配置しました。
すべてのソースコードは、<JDK7>/demo/nio/zipfs/src.zip で確認できますが、簡単に確認するなら、こちらからも確認できます。

次に2個目の目的のために、サンプルコードを用意しました。FILE_NAMEというZipファイルからSRC_NAMEを取り出すには以下のようにします。
try (FileSystem fs = FileSystems.newFileSystem(Paths.get(FILE_NAME), null)) {
           Files.copy(fs.getPath(SRC_NAME), Paths.get(DST_NAME);
}

もしくはZIPファイル上で"fancy nio2 walk"をするのならこんな感じ。
try (FileSystem fs = FileSystems.newFileSystem(Paths.get(FILE_NAME), null)) {
    Files.walkFileTree(fs.getPath(DIR_NAME),  new SimpleFileVisitor<Path>() {
            private int indent = 0;
            private void perform(Path file, BasicFileAttributes attrs) {
                if (attrs.isDirectory())
                    System.out.printf("%" + (indent==0?"":indent<<1) + "s[%s]%n", "", file.toString());
                else
                    System.out.printf("%" + (indent==0?"":indent<<1) + "s%s%n", "", file.getFileName().toString());
            }

            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                perform(file, attrs);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)  {
                perform(dir, attrs);
                indent += 2;
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException ioe) {
                indent -= 2;
                return FileVisitResult.CONTINUE;
            }
        }
    );
}
java.util.zipでできなかったこんなこともできます。例えば、作成時間と最終アクセス時間を持ったZipファイルにファイルをコピーします。
Files.copy(Paths.get(SRC), fs.getPath(DST), COPY_ATTRIBUTES);
 以下は上記のコードでDemo.javaをZipファイルにコピーした結果の出力サンプルです。
/Demo.java
    creationTime    : Fri Apr 29 22:41:46 PDT 2011
    lastAccessTime  : Wed May 25 20:58:36 PDT 2011
    lastModifiedTime: Fri Apr 29 22:41:46 PDT 2011
    isRegularFile   : true
    isDirectory     : false
    isSymbolicLink  : false
    isOther         : false
    fileKey         : null
    size            : 26680
    compressedSize  : 4941
    crc             : c5f6eb5a
    method          : 8
もっとクールなNIO/ZIPファイルシステムの利用方法はこちらでご覧頂けます。
<JDK7_HOME>/demo/nio/zipfs/Demo.java

ちゃんと動くようにするためには、<JDK>/demo/nio/zipfs/zipfs.jarをクラスパスに追加するか、lib/extディレクトリにzip.jarを追加する必要がありますが、JDK7/b123以後では、zipfs.jarはlib/extに追加されていますので、通常のファイルシステムのようにアクセスすることができます。

JDK7では、ZIPファイルシステムプロバイダはjava.net.JarURLConnectionで定めている従来のJAR URLをサポートしています。つまり、zip/JARファイルシステムは次のURIによって識別することができます。
jar:{uri}!/{entry}
さらに、ZIPファイルシステムは次のURIを使って作成できます。
jar:{uri}
最新のURL RFEと、従来のJAR URL構文の混在は開発者の混乱を招く可能性があるので、最新のURL RFEは取り扱わないことにしました。
JDK7では、zip/JARファイルはファイルシステム上になければならないので、URIスキーム"{uri}"にfileが入ります。例えば、
jar:file:/tmp/foo.jar
jar:file:/tmp/foo.jar!/bar
新しいFileSystemを作成すると、ファイルシステムを設定するためにプロパティを使うことがあります。これらのプロパティはjava.util.Mapを介してFileSystems.newFileSystemメソッドで指定します。
キーはプロパティ名(String)と値はプロパティ値です。新しく2個のプロパティをサポートします。
create: java.lang.String型、デフォルト値は"false"。"true"の場合(大文字小文字を認識します)、zipやJARファイルが存在しない場合に作成されます。
encoding: java.lang.String型、デフォルト値は"UTF-8"。Zipファイル、JARファイル中のエントリのエンコード名を示します。
近くにZipファイルやJarファイルがあれば試して見てください。そして改善点があればお知らせください。



原文はこちら。
http://blogs.oracle.com/xuemingshen/entry/the_zip_filesystem_provider_in1

0 件のコメント:

コメントを投稿