com.partnersoft.formats.boxcar
Class BoxcarLib

java.lang.Object
  extended by com.partnersoft.formats.boxcar.BoxcarLib
All Implemented Interfaces:
Lib

public class BoxcarLib
extends java.lang.Object
implements Lib

A simple filesystem archive format.

A boxcar consists of a short header followed by a list of file entries; each file entry has its full (relative) file path first in UTF format, followed by 8 bytes of currently unused flag information, followed by a 8-byte length, followed by the file's bytes. The whole is then (optionally) gzip-compressed.

Files are sorted asciibetically by path.

Boxcar is designed to be stable - multiple runs with the same filesystem and with no changes to the component files will produce identical boxcar files. It is also designed to be efficient - since all files are compressed together instead of individually, the result is generally smaller than archive formats like .zip that compress each file individually.

The streaming nature of both the layout and the compression allow boxcar to be used as an on-the-wire format; you do not have to actually create a boxcar file. On the other hand, the fact that there is no centralized listing of contents and the global compression means that simply scanning the contents to see what files are present is inefficient - in a compressed file, it takes as long to scan it as to unpack it. This makes boxcar unsuitable as a "live" filesystem (e.g. opening it up and digging through the contents without unpacking it).

The format is also designed to be cross-platform. UTF devolves to ASCII with a two-byte length prefix in most cases, so an almost-compliant reader and writer can be hoked up with ease. GZIP libraries are available for most modern operating systems and languages.

It is NOT the intent of boxcar to accurately reproduce a filesystem with permissions, dates, etc. Instead these are left out to facilitate com.partnersoft.update and similar schemes where the file date etc. would cause unnecessary changes in the update archive. For example, if a map set were translated twice and zipped up each time, the zipfiles would differ because of the changed dates and possibly due to ordering issues, even though the file data should be identical.

Copyright 2005 Partner Software, Inc.

Version:
$Id: BoxcarLib.java 2013 2009-08-10 03:29:31Z paul $
Author:
Paul Reavis

Method Summary
static java.util.List<Path> listContents(java.io.InputStream input, boolean gunzip)
          Scans a boxcar from the given stream and returns a listing of its contents.
static java.util.List<Path> listContents(VfsFile boxcarFile)
          Scans the given boxcar file and returns a list of the contents.
static void pack(java.io.OutputStream output, boolean gzip, java.lang.Iterable<VfsNode> nodes)
          Archives to the given stream in the boxcar format.
static void pack(java.io.OutputStream output, boolean gzip, VfsNode... nodes)
          Archives to the given stream in the boxcar format.
static void pack(VfsFile boxcar, java.lang.Iterable<VfsNode> nodes)
          Creates a new boxcar archive.
static void pack(VfsFile boxcar, VfsNode... nodes)
          Creates a new boxcar archive.
static void unpack(java.io.InputStream input, boolean gunzip, VfsDirectory destinationDir)
          Unpacks a boxcar from the given stream.
static void unpack(VfsFile boxcarFile)
          Unpacks the given boxcar file to the current installation directory.
static void unpack(VfsFile boxcarFile, VfsDirectory destinationDir)
          Unpacks a boxcar archive the given root directory.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Method Detail

pack

public static void pack(VfsFile boxcar,
                        VfsNode... nodes)
                 throws java.io.IOException
Creates a new boxcar archive. If the archive has a ".gz" extension, automatically compresses via gzip as well. The supplied list of nodes are included; any directories in the list are added recursively with all their contents.

Throws:
java.io.IOException

pack

public static void pack(VfsFile boxcar,
                        java.lang.Iterable<VfsNode> nodes)
                 throws java.io.IOException
Creates a new boxcar archive. If the archive has a ".gz" extension, automatically compresses via gzip as well. The supplied list of nodes are included; any directories in the list are added recursively with all their contents.

Throws:
java.io.IOException

pack

public static void pack(java.io.OutputStream output,
                        boolean gzip,
                        VfsNode... nodes)
                 throws java.io.IOException
Archives to the given stream in the boxcar format. If the gzip flag is true, gzips it; otherwise archives in uncompressed format. Does NOT automatically buffer; supply your own buffering if you want it (and you generally do!). The supplied list of nodes are included; any directories in the list are added recursively with all their contents.

Throws:
java.io.IOException

pack

public static void pack(java.io.OutputStream output,
                        boolean gzip,
                        java.lang.Iterable<VfsNode> nodes)
                 throws java.io.IOException
Archives to the given stream in the boxcar format. If the gzip flag is true, gzips it; otherwise archives in uncompressed format. Does NOT automatically buffer; supply your own buffering if you want it (and you generally do!). The supplied list of nodes are included; any directories in the list are added recursively with all their contents.

Throws:
java.io.IOException

unpack

public static void unpack(VfsFile boxcarFile)
                   throws java.io.IOException
Unpacks the given boxcar file to the current installation directory. If the file has a ".gz" extension, decompresses it via gzip as well.

Parameters:
boxcarFile - file to unpack
Throws:
java.io.IOException - if unpacking fails

unpack

public static void unpack(VfsFile boxcarFile,
                          VfsDirectory destinationDir)
                   throws java.io.IOException
Unpacks a boxcar archive the given root directory. If the archive has a ".gz" extension, automatically decompresses via gzip as well.

Throws:
java.io.IOException

unpack

public static void unpack(java.io.InputStream input,
                          boolean gunzip,
                          VfsDirectory destinationDir)
                   throws java.io.IOException
Unpacks a boxcar from the given stream. If gunzip is true, uncompresses it as well; otherwise it treats it as uncompressed input. Does not buffer the input stream - supply a buffered one if you want that (and you do!).

Throws:
java.io.IOException

listContents

public static java.util.List<Path> listContents(VfsFile boxcarFile)
                                         throws java.io.IOException
Scans the given boxcar file and returns a list of the contents. Note that this is not a terribly efficient operation.

Parameters:
boxcarFile - file to scan
Throws:
java.io.IOException - if unpacking fails

listContents

public static java.util.List<Path> listContents(java.io.InputStream input,
                                                boolean gunzip)
                                         throws java.io.IOException
Scans a boxcar from the given stream and returns a listing of its contents. If gunzip is true, uncompresses it as well; otherwise it treats it as uncompressed input. Does not buffer the input stream - supply a buffered one if you want that (and you do!).

Throws:
java.io.IOException