TarInputStream reads a UNIX tar archive as an InputStream : Zip Tar File « File Input Output « Java

Java
1. 2D Graphics GUI
2. 3D
3. Advanced Graphics
4. Ant
5. Apache Common
6. Chart
7. Class
8. Collections Data Structure
9. Data Type
10. Database SQL JDBC
11. Design Pattern
12. Development Class
13. EJB3
14. Email
15. Event
16. File Input Output
17. Game
18. Generics
19. GWT
20. Hibernate
21. I18N
22. J2EE
23. J2ME
24. JDK 6
25. JNDI LDAP
26. JPA
27. JSP
28. JSTL
29. Language Basics
30. Network Protocol
31. PDF RTF
32. Reflection
33. Regular Expressions
34. Scripting
35. Security
36. Servlets
37. Spring
38. Swing Components
39. Swing JFC
40. SWT JFace Eclipse
41. Threads
42. Tiny Application
43. Velocity
44. Web Services SOA
45. XML
Java Tutorial
Java Source Code / Java Documentation
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java » File Input Output » Zip Tar FileScreenshots 
TarInputStream reads a UNIX tar archive as an InputStream
     

/*
 ** Authored by Timothy Gerard Endres
 ** <mailto:time@gjt.org>  <http://www.trustice.com>
 ** 
 ** This work has been placed into the public domain.
 ** You may use this work in any way and for any purpose you wish.
 **
 ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND,
 ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR
 ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY
 ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR
 ** REDISTRIBUTION OF THIS SOFTWARE. 
 ** 
 */

import java.io.File;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;

/**
 * The TarInputStream reads a UNIX tar archive as an InputStream. methods are
 * provided to position at each successive entry in the archive, and the read
 * each entry as a normal input stream using read().
 
 @version $Revision: 12504 $
 @author Timothy Gerard Endres, <a
 *         href="mailto:time@gjt.org">time@trustice.com</a>.
 @see TarBuffer
 @see TarHeader
 @see TarEntry
 */

public class TarInputStream extends FilterInputStream {
  protected boolean debug;

  protected boolean hasHitEOF;

  protected int entrySize;

  protected int entryOffset;

  protected byte[] oneBuf;

  protected byte[] readBuf;

  protected TarBuffer buffer;

  protected TarEntry currEntry;

  protected EntryFactory eFactory;

  public TarInputStream(InputStream is) {
    this(is, TarBuffer.DEFAULT_BLKSIZE, TarBuffer.DEFAULT_RCDSIZE);
  }

  public TarInputStream(InputStream is, int blockSize) {
    this(is, blockSize, TarBuffer.DEFAULT_RCDSIZE);
  }

  public TarInputStream(InputStream is, int blockSize, int recordSize) {
    super(is);

    this.buffer = new TarBuffer(is, blockSize, recordSize);

    this.readBuf = null;
    this.oneBuf = new byte[1];
    this.debug = false;
    this.hasHitEOF = false;
    this.eFactory = null;
  }

  /**
   * Sets the debugging flag.
   
   @param debugF
   *          True to turn on debugging.
   */
  public void setDebug(boolean debugF) {
    this.debug = debugF;
  }

  /**
   * Sets the debugging flag.
   
   @param debugF
   *          True to turn on debugging.
   */
  public void setEntryFactory(EntryFactory factory) {
    this.eFactory = factory;
  }

  /**
   * Sets the debugging flag in this stream's TarBuffer.
   
   @param debugF
   *          True to turn on debugging.
   */
  public void setBufferDebug(boolean debug) {
    this.buffer.setDebug(debug);
  }

  /**
   * Closes this stream. Calls the TarBuffer's close() method.
   */
  public void close() throws IOException {
    this.buffer.close();
  }

  /**
   * Get the record size being used by this stream's TarBuffer.
   
   @return The TarBuffer record size.
   */
  public int getRecordSize() {
    return this.buffer.getRecordSize();
  }

  /**
   * Get the available data that can be read from the current entry in the
   * archive. This does not indicate how much data is left in the entire
   * archive, only in the current entry. This value is determined from the
   * entry's size header field and the amount of data already read from the
   * current entry.
   
   
   @return The number of available bytes for the current entry.
   */
  public int available() throws IOException {
    return this.entrySize - this.entryOffset;
  }

  /**
   * Skip bytes in the input buffer. This skips bytes in the current entry's
   * data, not the entire archive, and will stop at the end of the current
   * entry's data if the number to skip extends beyond that point.
   
   @param numToSkip
   *          The number of bytes to skip.
   */
  public void skip(int numToSkipthrows IOException {
    // REVIEW
    // This is horribly inefficient, but it ensures that we
    // properly skip over bytes via the TarBuffer...
    //

    byte[] skipBuf = new byte[1024];

    for (int num = numToSkip; num > 0;) {
      int numRead = this.read(skipBuf, 0(num > skipBuf.length ? skipBuf.length : num));

      if (numRead == -1)
        break;

      num -= numRead;
    }
  }

  /**
   * Since we do not support marking just yet, we return false.
   
   @return False.
   */
  public boolean markSupported() {
    return false;
  }

  /**
   * Since we do not support marking just yet, we do nothing.
   
   @param markLimit
   *          The limit to mark.
   */
  public void mark(int markLimit) {
  }

  /**
   * Since we do not support marking just yet, we do nothing.
   */
  public void reset() {
  }

  /**
   * Get the next entry in this tar archive. This will skip over any remaining
   * data in the current entry, if there is one, and place the input stream at
   * the header of the next entry, and read the header and instantiate a new
   * TarEntry from the header bytes and return that entry. If there are no more
   * entries in the archive, null will be returned to indicate that the end of
   * the archive has been reached.
   
   @return The next TarEntry in the archive, or null.
   */
  public TarEntry getNextEntry() throws IOException {
    if (this.hasHitEOF)
      return null;

    if (this.currEntry != null) {
      int numToSkip = this.entrySize - this.entryOffset;

      if (this.debug)
        System.err.println("TarInputStream: SKIP currENTRY '" this.currEntry.getName() "' SZ "
            this.entrySize + " OFF " this.entryOffset + "  skipping " + numToSkip + " bytes");

      if (numToSkip > 0) {
        this.skip(numToSkip);
      }

      this.readBuf = null;
    }

    byte[] headerBuf = this.buffer.readRecord();

    if (headerBuf == null) {
      if (this.debug) {
        System.err.println("READ NULL RECORD");
      }

      this.hasHitEOF = true;
    else if (this.buffer.isEOFRecord(headerBuf)) {
      if (this.debug) {
        System.err.println("READ EOF RECORD");
      }

      this.hasHitEOF = true;
    }

    if (this.hasHitEOF) {
      this.currEntry = null;
    else {
      try {
        if (this.eFactory == null) {
          this.currEntry = new TarEntry(headerBuf);
        else {
          this.currEntry = this.eFactory.createEntry(headerBuf);
        }

        if (!(headerBuf[257== 'u' && headerBuf[258== 's' && headerBuf[259== 't'
            && headerBuf[260== 'a' && headerBuf[261== 'r')) {
          throw new InvalidHeaderException("header magic is not 'ustar', but '" + headerBuf[257]
              + headerBuf[258+ headerBuf[259+ headerBuf[260+ headerBuf[261"', or (dec) "
              ((intheaderBuf[257]) ", " ((intheaderBuf[258]) ", "
              ((intheaderBuf[259]) ", " ((intheaderBuf[260]) ", "
              ((intheaderBuf[261]));
        }

        if (this.debug)
          System.err.println("TarInputStream: SET CURRENTRY '" this.currEntry.getName()
              "' size = " this.currEntry.getSize());

        this.entryOffset = 0;
        // REVIEW How do we resolve this discrepancy?!
        this.entrySize = (intthis.currEntry.getSize();
      catch (InvalidHeaderException ex) {
        this.entrySize = 0;
        this.entryOffset = 0;
        this.currEntry = null;
        throw new InvalidHeaderException("bad header in block " this.buffer.getCurrentBlockNum()
            " record " this.buffer.getCurrentRecordNum() ", " + ex.getMessage());
      }
    }

    return this.currEntry;
  }

  /**
   * Reads a byte from the current tar archive entry.
   
   * This method simply calls read( byte[], int, int ).
   
   @return The byte read, or -1 at EOF.
   */
  public int read() throws IOException {
    int num = this.read(this.oneBuf, 01);
    if (num == -1)
      return num;
    else
      return this.oneBuf[0];
  }

  /**
   * Reads bytes from the current tar archive entry.
   
   * This method simply calls read( byte[], int, int ).
   
   @param buf
   *          The buffer into which to place bytes read.
   @return The number of bytes read, or -1 at EOF.
   */
  public int read(byte[] bufthrows IOException {
    return this.read(buf, 0, buf.length);
  }

  /**
   * Reads bytes from the current tar archive entry.
   
   * This method is aware of the boundaries of the current entry in the archive
   * and will deal with them as if they were this stream's start and EOF.
   
   @param buf
   *          The buffer into which to place bytes read.
   @param offset
   *          The offset at which to place bytes read.
   @param numToRead
   *          The number of bytes to read.
   @return The number of bytes read, or -1 at EOF.
   */
  public int read(byte[] buf, int offset, int numToReadthrows IOException {
    int totalRead = 0;

    if (this.entryOffset >= this.entrySize)
      return -1;

    if ((numToRead + this.entryOffsetthis.entrySize) {
      numToRead = (this.entrySize - this.entryOffset);
    }

    if (this.readBuf != null) {
      int sz = (numToRead > this.readBuf.lengththis.readBuf.length : numToRead;

      System.arraycopy(this.readBuf, 0, buf, offset, sz);

      if (sz >= this.readBuf.length) {
        this.readBuf = null;
      else {
        int newLen = this.readBuf.length - sz;
        byte[] newBuf = new byte[newLen];
        System.arraycopy(this.readBuf, sz, newBuf, 0, newLen);
        this.readBuf = newBuf;
      }

      totalRead += sz;
      numToRead -= sz;
      offset += sz;
    }

    for (; numToRead > 0;) {
      byte[] rec = this.buffer.readRecord();
      if (rec == null) {
        // Unexpected EOF!
        throw new IOException("unexpected EOF with " + numToRead + " bytes unread");
      }

      int sz = numToRead;
      int recLen = rec.length;

      if (recLen > sz) {
        System.arraycopy(rec, 0, buf, offset, sz);
        this.readBuf = new byte[recLen - sz];
        System.arraycopy(rec, sz, this.readBuf, 0, recLen - sz);
      else {
        sz = recLen;
        System.arraycopy(rec, 0, buf, offset, recLen);
      }

      totalRead += sz;
      numToRead -= sz;
      offset += sz;
    }

    this.entryOffset += totalRead;

    return totalRead;
  }

  /**
   * Copies the contents of the current tar archive entry directly into an
   * output stream.
   
   @param out
   *          The OutputStream into which to write the entry's data.
   */
  public void copyEntryContents(OutputStream outthrows IOException {
    byte[] buf = new byte[32 1024];

    for (;;) {
      int numRead = this.read(buf, 0, buf.length);
      if (numRead == -1)
        break;
      out.write(buf, 0, numRead);
    }
  }

  /**
   * This interface is provided, with the method setEntryFactory(), to allow the
   * programmer to have their own TarEntry subclass instantiated for the entries
   * return from getNextEntry().
   */

  public interface EntryFactory {
    public TarEntry createEntry(String name);

    public TarEntry createEntry(File paththrows InvalidHeaderException;

    public TarEntry createEntry(byte[] headerBufthrows InvalidHeaderException;
  }

  public class EntryAdapter implements EntryFactory {
    public TarEntry createEntry(String name) {
      return new TarEntry(name);
    }

    public TarEntry createEntry(File paththrows InvalidHeaderException {
      return new TarEntry(path);
    }

    public TarEntry createEntry(byte[] headerBufthrows InvalidHeaderException {
      return new TarEntry(headerBuf);
    }
  }

}

/*
 * * Authored by Timothy Gerard Endres * <mailto:time@gjt.org>
 * <http://www.trustice.com> * * This work has been placed into the public
 * domain. * You may use this work in any way and for any purpose you wish. * *
 * THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, * NOT EVEN THE
 * IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR * OF THIS SOFTWARE, ASSUMES
 * _NO_ RESPONSIBILITY FOR ANY * CONSEQUENCE RESULTING FROM THE USE,
 * MODIFICATION, OR * REDISTRIBUTION OF THIS SOFTWARE. *
 */

/**
 * This class encapsulates the Tar Entry Header used in Tar Archives. The class
 * also holds a number of tar constants, used mostly in headers.
 */

class TarHeader extends Object {
  /**
   * The length of the name field in a header buffer.
   */
  public static final int NAMELEN = 100;

  /**
   * The length of the mode field in a header buffer.
   */
  public static final int MODELEN = 8;

  /**
   * The length of the user id field in a header buffer.
   */
  public static final int UIDLEN = 8;

  /**
   * The length of the group id field in a header buffer.
   */
  public static final int GIDLEN = 8;

  /**
   * The length of the checksum field in a header buffer.
   */
  public static final int CHKSUMLEN = 8;

  /**
   * The length of the size field in a header buffer.
   */
  public static final int SIZELEN = 12;

  /**
   * The length of the magic field in a header buffer.
   */
  public static final int MAGICLEN = 8;

  /**
   * The length of the modification time field in a header buffer.
   */
  public static final int MODTIMELEN = 12;

  /**
   * The length of the user name field in a header buffer.
   */
  public static final int UNAMELEN = 32;

  /**
   * The length of the group name field in a header buffer.
   */
  public static final int GNAMELEN = 32;

  /**
   * The length of the devices field in a header buffer.
   */
  public static final int DEVLEN = 8;

  /**
   * LF_ constants represent the "link flag" of an entry, or more commonly, the
   * "entry type". This is the "old way" of indicating a normal file.
   */
  public static final byte LF_OLDNORM = 0;

  /**
   * Normal file type.
   */
  public static final byte LF_NORMAL = (byte'0';

  /**
   * Link file type.
   */
  public static final byte LF_LINK = (byte'1';

  /**
   * Symbolic link file type.
   */
  public static final byte LF_SYMLINK = (byte'2';

  /**
   * Character device file type.
   */
  public static final byte LF_CHR = (byte'3';

  /**
   * Block device file type.
   */
  public static final byte LF_BLK = (byte'4';

  /**
   * Directory file type.
   */
  public static final byte LF_DIR = (byte'5';

  /**
   * FIFO (pipe) file type.
   */
  public static final byte LF_FIFO = (byte'6';

  /**
   * Contiguous file type.
   */
  public static final byte LF_CONTIG = (byte'7';

  /**
   * The magic tag representing a POSIX tar archive.
   */
  public static final String TMAGIC = "ustar";

  /**
   * The magic tag representing a GNU tar archive.
   */
  public static final String GNU_TMAGIC = "ustar  ";

  /**
   * The entry's name.
   */
  public StringBuffer name;

  /**
   * The entry's permission mode.
   */
  public int mode;

  /**
   * The entry's user id.
   */
  public int userId;

  /**
   * The entry's group id.
   */
  public int groupId;

  /**
   * The entry's size.
   */
  public long size;

  /**
   * The entry's modification time.
   */
  public long modTime;

  /**
   * The entry's checksum.
   */
  public int checkSum;

  /**
   * The entry's link flag.
   */
  public byte linkFlag;

  /**
   * The entry's link name.
   */
  public StringBuffer linkName;

  /**
   * The entry's magic tag.
   */
  public StringBuffer magic;

  /**
   * The entry's user name.
   */
  public StringBuffer userName;

  /**
   * The entry's group name.
   */
  public StringBuffer groupName;

  /**
   * The entry's major device number.
   */
  public int devMajor;

  /**
   * The entry's minor device number.
   */
  public int devMinor;

  public TarHeader() {
    this.magic = new StringBuffer(TarHeader.TMAGIC);

    this.name = new StringBuffer();
    this.linkName = new StringBuffer();

    String user = System.getProperty("user.name""");

    if (user.length() 31)
      user = user.substring(031);

    this.userId = 0;
    this.groupId = 0;
    this.userName = new StringBuffer(user);
    this.groupName = new StringBuffer("");
  }

  /**
   * TarHeaders can be cloned.
   */
  public Object clone() {
    TarHeader hdr = null;

    try {
      hdr = (TarHeadersuper.clone();

      hdr.name = (this.name == nullnull new StringBuffer(this.name.toString());
      hdr.mode = this.mode;
      hdr.userId = this.userId;
      hdr.groupId = this.groupId;
      hdr.size = this.size;
      hdr.modTime = this.modTime;
      hdr.checkSum = this.checkSum;
      hdr.linkFlag = this.linkFlag;
      hdr.linkName = (this.linkName == nullnull new StringBuffer(this.linkName.toString());
      hdr.magic = (this.magic == nullnull new StringBuffer(this.magic.toString());
      hdr.userName = (this.userName == nullnull new StringBuffer(this.userName.toString());
      hdr.groupName = (this.groupName == nullnull new StringBuffer(this.groupName.toString());
      hdr.devMajor = this.devMajor;
      hdr.devMinor = this.devMinor;
    catch (CloneNotSupportedException ex) {
      ex.printStackTrace();
    }

    return hdr;
  }

  /**
   * Get the name of this entry.
   
   @return Teh entry's name.
   */
  public String getName() {
    return this.name.toString();
  }

  /**
   * Parse an octal string from a header buffer. This is used for the file
   * permission mode value.
   
   @param header
   *          The header buffer from which to parse.
   @param offset
   *          The offset into the buffer from which to parse.
   @param length
   *          The number of header bytes to parse.
   @return The long value of the octal string.
   */
  public static long parseOctal(byte[] header, int offset, int length)
      throws InvalidHeaderException {
    long result = 0;
    boolean stillPadding = true;

    int end = offset + length;
    for (int i = offset; i < end; ++i) {
      if (header[i== 0)
        break;

      if (header[i== (byte' ' || header[i== '0') {
        if (stillPadding)
          continue;

        if (header[i== (byte' ')
          break;
      }

      stillPadding = false;

      result = (result << 3(header[i'0');
    }

    return result;
  }

  /**
   * Parse an entry name from a header buffer.
   
   @param header
   *          The header buffer from which to parse.
   @param offset
   *          The offset into the buffer from which to parse.
   @param length
   *          The number of header bytes to parse.
   @return The header's entry name.
   */
  public static StringBuffer parseName(byte[] header, int offset, int length)
      throws InvalidHeaderException {
    StringBuffer result = new StringBuffer(length);

    int end = offset + length;
    for (int i = offset; i < end; ++i) {
      if (header[i== 0)
        break;
      result.append((charheader[i]);
    }

    return result;
  }

  /**
   * Determine the number of bytes in an entry name.
   
   @param header
   *          The header buffer from which to parse.
   @param offset
   *          The offset into the buffer from which to parse.
   @param length
   *          The number of header bytes to parse.
   @return The number of bytes in a header's entry name.
   */
  public static int getNameBytes(StringBuffer name, byte[] buf, int offset, int length) {
    int i;

    for (i = 0; i < length && i < name.length(); ++i) {
      buf[offset + i(bytename.charAt(i);
    }

    for (; i < length; ++i) {
      buf[offset + i0;
    }

    return offset + length;
  }

  /**
   * Parse an octal integer from a header buffer.
   
   @param header
   *          The header buffer from which to parse.
   @param offset
   *          The offset into the buffer from which to parse.
   @param length
   *          The number of header bytes to parse.
   @return The integer value of the octal bytes.
   */
  public static int getOctalBytes(long value, byte[] buf, int offset, int length) {
    byte[] result = new byte[length];

    int idx = length - 1;

    buf[offset + idx0;
    --idx;
    buf[offset + idx(byte' ';
    --idx;

    if (value == 0) {
      buf[offset + idx(byte'0';
      --idx;
    else {
      for (long val = value; idx >= && val > 0; --idx) {
        buf[offset + idx(byte) ((byte'0' (byte) (val & 7));
        val = val >> 3;
      }
    }

    for (; idx >= 0; --idx) {
      buf[offset + idx(byte' ';
    }

    return offset + length;
  }

  /**
   * Parse an octal long integer from a header buffer.
   
   @param header
   *          The header buffer from which to parse.
   @param offset
   *          The offset into the buffer from which to parse.
   @param length
   *          The number of header bytes to parse.
   @return The long value of the octal bytes.
   */
  public static int getLongOctalBytes(long value, byte[] buf, int offset, int length) {
    byte[] temp = new byte[length + 1];
    TarHeader.getOctalBytes(value, temp, 0, length + 1);
    System.arraycopy(temp, 0, buf, offset, length);
    return offset + length;
  }

  /**
   * Parse the checksum octal integer from a header buffer.
   
   @param header
   *          The header buffer from which to parse.
   @param offset
   *          The offset into the buffer from which to parse.
   @param length
   *          The number of header bytes to parse.
   @return The integer value of the entry's checksum.
   */
  public static int getCheckSumOctalBytes(long value, byte[] buf, int offset, int length) {
    TarHeader.getOctalBytes(value, buf, offset, length);
    buf[offset + length - 1(byte' ';
    buf[offset + length - 20;
    return offset + length;
  }

}

/*
 * * Authored by Timothy Gerard Endres * <mailto:time@gjt.org>
 * <http://www.trustice.com> * * This work has been placed into the public
 * domain. * You may use this work in any way and for any purpose you wish. * *
 * THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, * NOT EVEN THE
 * IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR * OF THIS SOFTWARE, ASSUMES
 * _NO_ RESPONSIBILITY FOR ANY * CONSEQUENCE RESULTING FROM THE USE,
 * MODIFICATION, OR * REDISTRIBUTION OF THIS SOFTWARE. *
 */

/**
 
 * This class represents an entry in a Tar archive. It consists of the entry's
 * header, as well as the entry's File. Entries can be instantiated in one of
 * three ways, depending on how they are to be used.
 * <p>
 * TarEntries that are created from the header bytes read from an archive are
 * instantiated with the TarEntry( byte[] ) constructor. These entries will be
 * used when extracting from or listing the contents of an archive. These
 * entries have their header filled in using the header bytes. They also set the
 * File to null, since they reference an archive entry not a file.
 * <p>
 * TarEntries that are created from Files that are to be written into an archive
 * are instantiated with the TarEntry( File ) constructor. These entries have
 * their header filled in using the File's information. They also keep a
 * reference to the File for convenience when writing entries.
 * <p>
 * Finally, TarEntries can be constructed from nothing but a name. This allows
 * the programmer to construct the entry by hand, for instance when only an
 * InputStream is available for writing to the archive, and the header
 * information is constructed from other information. In this case the header
 * fields are set to defaults and the File is set to null.
 
 * <p>
 * The C structure for a Tar Entry's header is:
 
 * <pre>
 *  struct header {
 *    char  name[NAMSIZ];
 *    char  mode[8];
 *    char  uid[8];
 *    char  gid[8];
 *    char  size[12];
 *    char  mtime[12];
 *    char  chksum[8];
 *    char  linkflag;
 *    char  linkname[NAMSIZ];
 *    char  magic[8];
 *    char  uname[TUNMLEN];
 *    char  gname[TGNMLEN];
 *    char  devmajor[8];
 *    char  devminor[8];
 *  } header;
 * </pre>
 
 @see TarHeader
 
 */

class TarEntry extends Object {
  /**
   * If this entry represents a File, this references it.
   */
  protected File file;

  /**
   * This is the entry's header information.
   */
  protected TarHeader header;

  /**
   * Construct an entry with only a name. This allows the programmer to
   * construct the entry's header "by hand". File is set to null.
   */
  public TarEntry(String name) {
    this.initialize();
    this.nameTarHeader(this.header, name);
  }

  /**
   * Construct an entry for a file. File is set to file, and the header is
   * constructed from information from the file.
   
   @param file
   *          The file that the entry represents.
   */
  public TarEntry(File filethrows InvalidHeaderException {
    this.initialize();
    this.getFileTarHeader(this.header, file);
  }

  /**
   * Construct an entry from an archive's header bytes. File is set to null.
   
   @param headerBuf
   *          The header bytes from a tar archive entry.
   */
  public TarEntry(byte[] headerBufthrows InvalidHeaderException {
    this.initialize();
    this.parseTarHeader(this.header, headerBuf);
  }

  /**
   * Initialization code common to all constructors.
   */
  private void initialize() {
    this.file = null;
    this.header = new TarHeader();
  }

  /**
   * Determine if the two entries are equal. Equality is determined by the
   * header names being equal.
   
   @return it Entry to be checked for equality.
   @return True if the entries are equal.
   */
  public boolean equals(TarEntry it) {
    return this.header.name.toString().equals(it.header.name.toString());
  }

  /**
   * Determine if the given entry is a descendant of this entry. Descendancy is
   * determined by the name of the descendant starting with this entry's name.
   
   @param desc
   *          Entry to be checked as a descendent of this.
   @return True if entry is a descendant of this.
   */
  public boolean isDescendent(TarEntry desc) {
    return desc.header.name.toString().startsWith(this.header.name.toString());
  }

  /**
   * Get this entry's header.
   
   @return This entry's TarHeader.
   */
  public TarHeader getHeader() {
    return this.header;
  }

  /**
   * Get this entry's name.
   
   @return This entry's name.
   */
  public String getName() {
    return this.header.name.toString();
  }

  /**
   * Set this entry's name.
   
   @param name
   *          This entry's new name.
   */
  public void setName(String name) {
    this.header.name = new StringBuffer(name);
  }

  /**
   * Get this entry's user id.
   
   @return This entry's user id.
   */
  public int getUserId() {
    return this.header.userId;
  }

  /**
   * Set this entry's user id.
   
   @param userId
   *          This entry's new user id.
   */
  public void setUserId(int userId) {
    this.header.userId = userId;
  }

  /**
   * Get this entry's group id.
   
   @return This entry's group id.
   */
  public int getGroupId() {
    return this.header.groupId;
  }

  /**
   * Set this entry's group id.
   
   @param groupId
   *          This entry's new group id.
   */
  public void setGroupId(int groupId) {
    this.header.groupId = groupId;
  }

  /**
   * Get this entry's user name.
   
   @return This entry's user name.
   */
  public String getUserName() {
    return this.header.userName.toString();
  }

  /**
   * Set this entry's user name.
   
   @param userName
   *          This entry's new user name.
   */
  public void setUserName(String userName) {
    this.header.userName = new StringBuffer(userName);
  }

  /**
   * Get this entry's group name.
   
   @return This entry's group name.
   */
  public String getGroupName() {
    return this.header.groupName.toString();
  }

  /**
   * Set this entry's group name.
   
   @param groupName
   *          This entry's new group name.
   */
  public void setGroupName(String groupName) {
    this.header.groupName = new StringBuffer(groupName);
  }

  /**
   * Convenience method to set this entry's group and user ids.
   
   @param userId
   *          This entry's new user id.
   @param groupId
   *          This entry's new group id.
   */
  public void setIds(int userId, int groupId) {
    this.setUserId(userId);
    this.setGroupId(groupId);
  }

  /**
   * Convenience method to set this entry's group and user names.
   
   @param userName
   *          This entry's new user name.
   @param groupName
   *          This entry's new group name.
   */
  public void setNames(String userName, String groupName) {
    this.setUserName(userName);
    this.setGroupName(groupName);
  }

  /**
   * Set this entry's modification time. The parameter passed to this method is
   * in "Java time".
   
   @param time
   *          This entry's new modification time.
   */
  public void setModTime(long time) {
    this.header.modTime = time / 1000;
  }

  /**
   * Set this entry's modification time.
   
   @param time
   *          This entry's new modification time.
   */
  public void setModTime(Date time) {
    this.header.modTime = time.getTime() 1000;
  }

  /**
   * Set this entry's modification time.
   
   @param time
   *          This entry's new modification time.
   */
  public Date getModTime() {
    return new Date(this.header.modTime * 1000);
  }

  /**
   * Get this entry's file.
   
   @return This entry's file.
   */
  public File getFile() {
    return this.file;
  }

  /**
   * Get this entry's file size.
   
   @return This entry's file size.
   */
  public long getSize() {
    return this.header.size;
  }

  /**
   * Set this entry's file size.
   
   @param size
   *          This entry's new file size.
   */
  public void setSize(long size) {
    this.header.size = size;
  }

  /**
   * Convenience method that will modify an entry's name directly in place in an
   * entry header buffer byte array.
   
   @param outbuf
   *          The buffer containing the entry header to modify.
   @param newName
   *          The new name to place into the header buffer.
   */
  public void adjustEntryName(byte[] outbuf, String newName) {
    int offset = 0;
    offset = TarHeader.getNameBytes(new StringBuffer(newName), outbuf, offset, TarHeader.NAMELEN);
  }

  /**
   * Return whether or not this entry represents a directory.
   
   @return True if this entry is a directory.
   */
  public boolean isDirectory() {
    if (this.file != null)
      return this.file.isDirectory();

    if (this.header != null) {
      if (this.header.linkFlag == TarHeader.LF_DIR)
        return true;

      if (this.header.name.toString().endsWith("/"))
        return true;
    }

    return false;
  }

  /**
   * Fill in a TarHeader with information from a File.
   
   @param hdr
   *          The TarHeader to fill in.
   @param file
   *          The file from which to get the header information.
   */
  public void getFileTarHeader(TarHeader hdr, File filethrows InvalidHeaderException {
    this.file = file;

    String name = file.getPath();
    String osname = System.getProperty("os.name");
    if (osname != null) {
      // Strip off drive letters!
      // REVIEW Would a better check be "(File.separator == '\')"?

      // String Win32Prefix = "Windows";
      // String prefix = osname.substring( 0, Win32Prefix.length() );
      // if ( prefix.equalsIgnoreCase( Win32Prefix ) )

      // if ( File.separatorChar == '\\' )

      // Per Patrick Beard:
      String Win32Prefix = "windows";
      if (osname.toLowerCase().startsWith(Win32Prefix)) {
        if (name.length() 2) {
          char ch1 = name.charAt(0);
          char ch2 = name.charAt(1);
          if (ch2 == ':' && ((ch1 >= 'a' && ch1 <= 'z'|| (ch1 >= 'A' && ch1 <= 'Z'))) {
            name = name.substring(2);
          }
        }
      }
    }

    name = name.replace(File.separatorChar, '/');

    // No absolute pathnames
    // Windows (and Posix?) paths can start with "\\NetworkDrive\",
    // so we loop on starting /'s.

    for (; name.startsWith("/");)
      name = name.substring(1);

    hdr.linkName = new StringBuffer("");

    hdr.name = new StringBuffer(name);

    if (file.isDirectory()) {
      hdr.mode = 040755;
      hdr.linkFlag = TarHeader.LF_DIR;
      if (hdr.name.charAt(hdr.name.length() 1!= '/')
        hdr.name.append("/");
    else {
      hdr.mode = 0100644;
      hdr.linkFlag = TarHeader.LF_NORMAL;
    }

    // UNDONE When File lets us get the userName, use it!

    hdr.size = file.length();
    hdr.modTime = file.lastModified() 1000;
    hdr.checkSum = 0;
    hdr.devMajor = 0;
    hdr.devMinor = 0;
  }

  /**
   * If this entry represents a file, and the file is a directory, return an
   * array of TarEntries for this entry's children.
   
   @return An array of TarEntry's for this entry's children.
   */
  public TarEntry[] getDirectoryEntries() throws InvalidHeaderException {
    if (this.file == null || !this.file.isDirectory()) {
      return new TarEntry[0];
    }

    String[] list = this.file.list();

    TarEntry[] result = new TarEntry[list.length];

    for (int i = 0; i < list.length; ++i) {
      result[inew TarEntry(new File(this.file, list[i]));
    }

    return result;
  }

  /**
   * Compute the checksum of a tar entry header.
   
   @param buf
   *          The tar entry's header buffer.
   @return The computed checksum.
   */
  public long computeCheckSum(byte[] buf) {
    long sum = 0;

    for (int i = 0; i < buf.length; ++i) {
      sum += 255 & buf[i];
    }

    return sum;
  }

  /**
   * Write an entry's header information to a header buffer.
   
   @param outbuf
   *          The tar entry header buffer to fill in.
   */
  public void writeEntryHeader(byte[] outbuf) {
    int offset = 0;

    offset = TarHeader.getNameBytes(this.header.name, outbuf, offset, TarHeader.NAMELEN);

    offset = TarHeader.getOctalBytes(this.header.mode, outbuf, offset, TarHeader.MODELEN);

    offset = TarHeader.getOctalBytes(this.header.userId, outbuf, offset, TarHeader.UIDLEN);

    offset = TarHeader.getOctalBytes(this.header.groupId, outbuf, offset, TarHeader.GIDLEN);

    long size = this.header.size;

    offset = TarHeader.getLongOctalBytes(size, outbuf, offset, TarHeader.SIZELEN);

    offset = TarHeader.getLongOctalBytes(this.header.modTime, outbuf, offset, TarHeader.MODTIMELEN);

    int csOffset = offset;
    for (int c = 0; c < TarHeader.CHKSUMLEN; ++c)
      outbuf[offset++(byte' ';

    outbuf[offset++this.header.linkFlag;

    offset = TarHeader.getNameBytes(this.header.linkName, outbuf, offset, TarHeader.NAMELEN);

    offset = TarHeader.getNameBytes(this.header.magic, outbuf, offset, TarHeader.MAGICLEN);

    offset = TarHeader.getNameBytes(this.header.userName, outbuf, offset, TarHeader.UNAMELEN);

    offset = TarHeader.getNameBytes(this.header.groupName, outbuf, offset, TarHeader.GNAMELEN);

    offset = TarHeader.getOctalBytes(this.header.devMajor, outbuf, offset, TarHeader.DEVLEN);

    offset = TarHeader.getOctalBytes(this.header.devMinor, outbuf, offset, TarHeader.DEVLEN);

    for (; offset < outbuf.length;)
      outbuf[offset++0;

    long checkSum = this.computeCheckSum(outbuf);

    TarHeader.getCheckSumOctalBytes(checkSum, outbuf, csOffset, TarHeader.CHKSUMLEN);
  }

  /**
   * Parse an entry's TarHeader information from a header buffer.
   
   @param hdr
   *          The TarHeader to fill in from the buffer information.
   @param header
   *          The tar entry header buffer to get information from.
   */
  public void parseTarHeader(TarHeader hdr, byte[] headerthrows InvalidHeaderException {
    int offset = 0;

    hdr.name = TarHeader.parseName(header, offset, TarHeader.NAMELEN);

    offset += TarHeader.NAMELEN;

    hdr.mode = (intTarHeader.parseOctal(header, offset, TarHeader.MODELEN);

    offset += TarHeader.MODELEN;

    hdr.userId = (intTarHeader.parseOctal(header, offset, TarHeader.UIDLEN);

    offset += TarHeader.UIDLEN;

    hdr.groupId = (intTarHeader.parseOctal(header, offset, TarHeader.GIDLEN);

    offset += TarHeader.GIDLEN;

    hdr.size = TarHeader.parseOctal(header, offset, TarHeader.SIZELEN);

    offset += TarHeader.SIZELEN;

    hdr.modTime = TarHeader.parseOctal(header, offset, TarHeader.MODTIMELEN);

    offset += TarHeader.MODTIMELEN;

    hdr.checkSum = (intTarHeader.parseOctal(header, offset, TarHeader.CHKSUMLEN);

    offset += TarHeader.CHKSUMLEN;

    hdr.linkFlag = header[offset++];

    hdr.linkName = TarHeader.parseName(header, offset, TarHeader.NAMELEN);

    offset += TarHeader.NAMELEN;

    hdr.magic = TarHeader.parseName(header, offset, TarHeader.MAGICLEN);

    offset += TarHeader.MAGICLEN;

    hdr.userName = TarHeader.parseName(header, offset, TarHeader.UNAMELEN);

    offset += TarHeader.UNAMELEN;

    hdr.groupName = TarHeader.parseName(header, offset, TarHeader.GNAMELEN);

    offset += TarHeader.GNAMELEN;

    hdr.devMajor = (intTarHeader.parseOctal(header, offset, TarHeader.DEVLEN);

    offset += TarHeader.DEVLEN;

    hdr.devMinor = (intTarHeader.parseOctal(header, offset, TarHeader.DEVLEN);
  }

  /**
   * Fill in a TarHeader given only the entry's name.
   
   @param hdr
   *          The TarHeader to fill in.
   @param name
   *          The tar entry name.
   */
  public void nameTarHeader(TarHeader hdr, String name) {
    boolean isDir = name.endsWith("/");

    hdr.checkSum = 0;
    hdr.devMajor = 0;
    hdr.devMinor = 0;

    hdr.name = new StringBuffer(name);
    hdr.mode = isDir ? 040755 0100644;
    hdr.userId = 0;
    hdr.groupId = 0;
    hdr.size = 0;
    hdr.checkSum = 0;

    hdr.modTime = (new java.util.Date()).getTime() 1000;

    hdr.linkFlag = isDir ? TarHeader.LF_DIR : TarHeader.LF_NORMAL;

    hdr.linkName = new StringBuffer("");
    hdr.userName = new StringBuffer("");
    hdr.groupName = new StringBuffer("");

    hdr.devMajor = 0;
    hdr.devMinor = 0;
  }

}

/**
 * The TarBuffer class implements the tar archive concept of a buffered input
 * stream. This concept goes back to the days of blocked tape drives and special
 * io devices. In the Java universe, the only real function that this class
 * performs is to ensure that files have the correct "block" size, or other tars
 * will complain.
 * <p>
 * You should never have a need to access this class directly. TarBuffers are
 * created by Tar IO Streams.
 
 @version $Revision: 12504 $
 @author Timothy Gerard Endres, <a
 *         href="mailto:time@gjt.org">time@trustice.com</a>.
 @see TarArchive
 */
class TarBuffer extends Object {
  public static final int DEFAULT_RCDSIZE = (512);

  public static final int DEFAULT_BLKSIZE = (DEFAULT_RCDSIZE * 20);

  private InputStream inStream;

  private OutputStream outStream;

  private byte[] blockBuffer;

  private int currBlkIdx;

  private int currRecIdx;

  private int blockSize;

  private int recordSize;

  private int recsPerBlock;

  private boolean debug;

  public TarBuffer(InputStream inStream) {
    this(inStream, TarBuffer.DEFAULT_BLKSIZE);
  }

  public TarBuffer(InputStream inStream, int blockSize) {
    this(inStream, blockSize, TarBuffer.DEFAULT_RCDSIZE);
  }

  public TarBuffer(InputStream inStream, int blockSize, int recordSize) {
    this.inStream = inStream;
    this.outStream = null;
    this.initialize(blockSize, recordSize);
  }

  public TarBuffer(OutputStream outStream) {
    this(outStream, TarBuffer.DEFAULT_BLKSIZE);
  }

  public TarBuffer(OutputStream outStream, int blockSize) {
    this(outStream, blockSize, TarBuffer.DEFAULT_RCDSIZE);
  }

  public TarBuffer(OutputStream outStream, int blockSize, int recordSize) {
    this.inStream = null;
    this.outStream = outStream;
    this.initialize(blockSize, recordSize);
  }

  /**
   * Initialization common to all constructors.
   */
  private void initialize(int blockSize, int recordSize) {
    this.debug = false;
    this.blockSize = blockSize;
    this.recordSize = recordSize;
    this.recsPerBlock = (this.blockSize / this.recordSize);
    this.blockBuffer = new byte[this.blockSize];

    if (this.inStream != null) {
      this.currBlkIdx = -1;
      this.currRecIdx = this.recsPerBlock;
    else {
      this.currBlkIdx = 0;
      this.currRecIdx = 0;
    }
  }

  /**
   * Get the TAR Buffer's block size. Blocks consist of multiple records.
   */
  public int getBlockSize() {
    return this.blockSize;
  }

  /**
   * Get the TAR Buffer's record size.
   */
  public int getRecordSize() {
    return this.recordSize;
  }

  /**
   * Set the debugging flag for the buffer.
   
   @param debug
   *          If true, print debugging output.
   */
  public void setDebug(boolean debug) {
    this.debug = debug;
  }

  /**
   * Determine if an archive record indicate End of Archive. End of archive is
   * indicated by a record that consists entirely of null bytes.
   
   @param record
   *          The record data to check.
   */
  public boolean isEOFRecord(byte[] record) {
    for (int i = 0, sz = this.getRecordSize(); i < sz; ++i)
      if (record[i!= 0)
        return false;

    return true;
  }

  /**
   * Skip over a record on the input stream.
   */

  public void skipRecord() throws IOException {
    if (this.debug) {
      System.err
          .println("SkipRecord: recIdx = " this.currRecIdx + " blkIdx = " this.currBlkIdx);
    }

    if (this.inStream == null)
      throw new IOException("reading (via skip) from an output buffer");

    if (this.currRecIdx >= this.recsPerBlock) {
      if (!this.readBlock())
        return// UNDONE
    }

    this.currRecIdx++;
  }

  /**
   * Read a record from the input stream and return the data.
   
   @return The record data.
   */

  public byte[] readRecord() throws IOException {
    if (this.debug) {
      System.err
          .println("ReadRecord: recIdx = " this.currRecIdx + " blkIdx = " this.currBlkIdx);
    }

    if (this.inStream == null)
      throw new IOException("reading from an output buffer");

    if (this.currRecIdx >= this.recsPerBlock) {
      if (!this.readBlock())
        return null;
    }

    byte[] result = new byte[this.recordSize];

    System.arraycopy(this.blockBuffer, (this.currRecIdx * this.recordSize), result, 0,
        this.recordSize);

    this.currRecIdx++;

    return result;
  }

  /**
   @return false if End-Of-File, else true
   */

  private boolean readBlock() throws IOException {
    if (this.debug) {
      System.err.println("ReadBlock: blkIdx = " this.currBlkIdx);
    }

    if (this.inStream == null)
      throw new IOException("reading from an output buffer");

    this.currRecIdx = 0;

    int offset = 0;
    int bytesNeeded = this.blockSize;
    for (; bytesNeeded > 0;) {
      long numBytes = this.inStream.read(this.blockBuffer, offset, bytesNeeded);

      //
      // NOTE
      // We have fit EOF, and the block is not full!
      //
      // This is a broken archive. It does not follow the standard
      // blocking algorithm. However, because we are generous, and
      // it requires little effort, we will simply ignore the error
      // and continue as if the entire block were read. This does
      // not appear to break anything upstream. We used to return
      // false in this case.
      //
      // Thanks to 'Yohann.Roussel@alcatel.fr' for this fix.
      //

      if (numBytes == -1)
        break;

      offset += numBytes;
      bytesNeeded -= numBytes;
      if (numBytes != this.blockSize) {
        if (this.debug) {
          System.err.println("ReadBlock: INCOMPLETE READ " + numBytes + " of " this.blockSize
              " bytes read.");
        }
      }
    }

    this.currBlkIdx++;

    return true;
  }

  /**
   * Get the current block number, zero based.
   
   @return The current zero based block number.
   */
  public int getCurrentBlockNum() {
    return this.currBlkIdx;
  }

  /**
   * Get the current record number, within the current block, zero based. Thus,
   * current offset = (currentBlockNum * recsPerBlk) + currentRecNum.
   
   @return The current zero based record number.
   */
  public int getCurrentRecordNum() {
    return this.currRecIdx - 1;
  }

  /**
   * Write an archive record to the archive.
   
   @param record
   *          The record data to write to the archive.
   */

  public void writeRecord(byte[] recordthrows IOException {
    if (this.debug) {
      System.err.println("WriteRecord: recIdx = " this.currRecIdx + " blkIdx = "
          this.currBlkIdx);
    }

    if (this.outStream == null)
      throw new IOException("writing to an input buffer");

    if (record.length != this.recordSize)
      throw new IOException("record to write has length '" + record.length
          "' which is not the record size of '" this.recordSize + "'");

    if (this.currRecIdx >= this.recsPerBlock) {
      this.writeBlock();
    }

    System.arraycopy(record, 0this.blockBuffer, (this.currRecIdx * this.recordSize),
        this.recordSize);

    this.currRecIdx++;
  }

  /**
   * Write an archive record to the archive, where the record may be inside of a
   * larger array buffer. The buffer must be "offset plus record size" long.
   
   @param buf
   *          The buffer containing the record data to write.
   @param offset
   *          The offset of the record data within buf.
   */

  public void writeRecord(byte[] buf, int offsetthrows IOException {
    if (this.debug) {
      System.err.println("WriteRecord: recIdx = " this.currRecIdx + " blkIdx = "
          this.currBlkIdx);
    }

    if (this.outStream == null)
      throw new IOException("writing to an input buffer");

    if ((offset + this.recordSize> buf.length)
      throw new IOException("record has length '" + buf.length + "' with offset '" + offset
          "' which is less than the record size of '" this.recordSize + "'");

    if (this.currRecIdx >= this.recsPerBlock) {
      this.writeBlock();
    }

    System.arraycopy(buf, offset, this.blockBuffer, (this.currRecIdx * this.recordSize),
        this.recordSize);

    this.currRecIdx++;
  }

  /**
   * Write a TarBuffer block to the archive.
   */
  private void writeBlock() throws IOException {
    if (this.debug) {
      System.err.println("WriteBlock: blkIdx = " this.currBlkIdx);
    }

    if (this.outStream == null)
      throw new IOException("writing to an input buffer");

    this.outStream.write(this.blockBuffer, 0this.blockSize);
    this.outStream.flush();

    this.currRecIdx = 0;
    this.currBlkIdx++;
  }

  /**
   * Flush the current data block if it has any data in it.
   */

  private void flushBlock() throws IOException {
    if (this.debug) {
      System.err.println("TarBuffer.flushBlock() called.");
    }

    if (this.outStream == null)
      throw new IOException("writing to an input buffer");

    if (this.currRecIdx > 0) {
      this.writeBlock();
    }
  }

  /**
   * Close the TarBuffer. If this is an output buffer, also flush the current
   * block before closing.
   */
  public void close() throws IOException {
    if (this.debug) {
      System.err.println("TarBuffer.closeBuffer().");
    }

    if (this.outStream != null) {
      this.flushBlock();

      if (this.outStream != System.out && this.outStream != System.err) {
        this.outStream.close();
        this.outStream = null;
      }
    else if (this.inStream != null) {
      if (this.inStream != System.in) {
        this.inStream.close();
        this.inStream = null;
      }
    }
  }

}

class InvalidHeaderException extends IOException {

  public InvalidHeaderException() {
    super();
  }

  public InvalidHeaderException(String msg) {
    super(msg);
  }

}

   
    
    
    
    
  
Related examples in the same category
1. Extract contents of a zip file
2. List the contents of a zip file
3. Read entries in a zip / compressed file
4. Decompress a zip file using ZipInputStream
5. Decompress a zip file using ZipFile
6. Create checksum for a zip file
7. Read a zip file checksum value
8. Create a zip file with java.util.zip package
9. Extract file/files from a zip file
10. Read files within a zip file
11. Retrieve a compressed file from a ZIP file
12. Retrieve the contents of a ZIP file
13. Making a zip file of directory including its subdirectories recursively
14. Displaying contents of a compressed zip file
15. Compress a Byte Array
16. Decompress a Byte Array
17. Read zip file
18. Write Zip file
19. The java.util.zip package can be used to create a checksum.
20. Read the content of a zip file ZipFile
21. List the entries of a zip file
22. Compressing Streams: Zipper, Java example
23. Compressing Streams: Parity Checksum
24. Compressing Streams: File Summer
25. Create a simple ZIP File: not retain any directory path information about the files.
26. Decompress a ZIP file.
27. Decompressing a Byte Array
28. Zip unzip byte array
29. Creating a ZIP File
30. Listing the Contents of a ZIP File
31. Retrieving a Compressed File from a ZIP File
32. Calculating the Checksum of a Byte Array (Compute Adler-32 checksum)
33. Compute CRC-32 checksum
34. Calculating the Checksum of a File
35. Compress string(byte array) by Deflater
36. Use Java code to zip a folder
37. Uses Zip compression to compress any number of files given on the command line
38. Load zip file and scan zip file
39. Reading the Contents of a ZIP File
40. UnZip -- print or unzip a JAR or PKZIP file using java.util.zip
41. Tape Archive Lister: Tar file
42. Compressing a Byte Array
43. Tar file stream
44. Tar file and untar file
45. bzip source code
46. Unpack an archive from a URL
47. Compare two zip files
48. Determine whether a file is a ZIP File.
49. Zip up a directory
50. Check sum for a path
51. Check sum for an InputStream
52. Extract zip file to destination folder
53. Return the first directory of this archive. This is needed to determine the plugin directory
54. Makes a zip file named xmlFileName from xmlURL at path
55. Unzipps a zip file placed at zipURL to path
56. A single checksum calculation for multiple files
57. Put file To Zip File
58. Provides both writing and reading from a file which is transparently compressed in Zip
59. TarOutputStream writes a UNIX tar archive as an OutputStream
60. Package files utility
61. Zip Compare
62. Unpack a segment from a zip
63. Unpack a zip file
64. Unzip file to a directory
65. Zip a list of file into one zip file.
66. Validate that an archive contains a named entry
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.