OSDN Git Service

Fix checkstyle warning
[dictzip-java/dictzip-java.git] / dictzip-lib / src / main / java / org / dict / zip / DictZipInputStream.java
index cd96659..a0a142c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * DictZip library.
  *
- * Copyright (C) 2001-2004 JDictd project.
+ * Copyright (C) 2001-2004 Ho Ngoc Duc
  * Copyright (C) 2016 Hiroshi Miura
  *
  * This program is free software; you can redistribute it and/or
 
 package org.dict.zip;
 
-import java.io.ByteArrayInputStream;
 import java.io.EOFException;
 import java.io.IOException;
-import java.io.InputStream;
-import java.io.SequenceInputStream;
-import java.text.MessageFormat;
 
 import java.util.zip.CRC32;
 import java.util.zip.Inflater;
@@ -36,7 +32,7 @@ import java.util.zip.InflaterInputStream;
 /**
  * DictZipInputStream.
  *
- * @author jdictd project
+ * @author Ho Ngoc Duc
  * @author Hiroshi Miura
  */
 public class DictZipInputStream extends InflaterInputStream {
@@ -55,14 +51,37 @@ public class DictZipInputStream extends InflaterInputStream {
     private long totalLength = 0;
     private long compLength = 0;
 
-    private int bufferSize;
     private int offset = 0;
 
+    private static final int BUF_LEN = 8192;
+
     /**
      * Indicates end of input stream.
      */
     private boolean eos;
 
+    /*
+     * Super class has three protected variables.
+     * protected byte[] buf
+     *                         Input buffer for decompression.
+     * protected Inflater inf
+     *                         Decompressor for this stream.
+     * protected int len
+     *                         Length of input buffer.
+     *
+     * We should not use these names in order to avoid confusion.
+     */
+
+    /**
+     * Creates a new input stream with a default buffer size from given filepath.
+     *
+     * @param filename the input filename
+     * @exception IOException if an I/O error has occurred
+     */
+    public DictZipInputStream(final String filename) throws IOException {
+        this(new RandomAccessInputStream(filename, "r"), BUF_LEN);
+    }
+
     /**
      * Creates a new input stream with a default buffer size.
      *
@@ -70,7 +89,7 @@ public class DictZipInputStream extends InflaterInputStream {
      * @exception IOException if an I/O error has occurred
      */
     public DictZipInputStream(final RandomAccessInputStream in) throws IOException {
-        this(in, 512);
+        this(in, BUF_LEN);
     }
 
     /**
@@ -83,7 +102,7 @@ public class DictZipInputStream extends InflaterInputStream {
     public DictZipInputStream(final RandomAccessInputStream in, final int size) throws IOException {
         super(in, new Inflater(true), size);
         header = readHeader();
-        bufferSize = size;
+        readTrailer();
     }
 
     /**
@@ -102,7 +121,7 @@ public class DictZipInputStream extends InflaterInputStream {
      * Reads uncompressed data into an array of bytes. Blocks until enough input is available for
      * decompression.
      *
-     * @param buf the buffer into which the data is read
+     * @param buffer the buffer into which the data is read
      * @param off the start offset of the data
      * @param size the maximum number of bytes read
      * @return the actual number of bytes read, or -1 if the end of the compressed input stream is
@@ -110,25 +129,42 @@ public class DictZipInputStream extends InflaterInputStream {
      * @exception IOException if an I/O error has occurred or the compressed input data is corrupt
      */
     @Override
-    public final int read(final byte[] buf, final int off, final int size) throws IOException {
+    public final int read(final byte[] buffer, final int off, final int size) throws IOException {
         if (eos) {
             return -1;
         }
-        int readLen;
-        if (offset == 0) {
-            readLen = super.read(buf, off, size);
-        } else {
-            byte[] tmpBuf = new byte[Math.min(offset + size, bufferSize - off)];
-            readLen = super.read(tmpBuf, 0, Math.min(offset + size, bufferSize - off));
-            int copyLen = Math.min(readLen - offset, size);
-            for (int i = 0; i < copyLen; i++) {
-                buf[off + i] = tmpBuf[offset + i];
+        if (buffer == null) {
+            throw new NullPointerException();
+        } else if (off < 0 || size < 0 || size > buffer.length - off || off >= buffer.length) {
+            throw new IndexOutOfBoundsException();
+        } else if (size == 0) {
+            return 0;
+        }
+        // skip to offset
+        if (offset > 0) {
+            int total;
+            int len;
+            byte[] b = new byte[512];
+            for (total = 0; total < offset; total += len) {
+                len = offset - total;
+                if (len > b.length) {
+                    len = b.length;
+                }
+
+                len = super.read(b, 0, len);
+                if (len == -1) {
+                    eos = true;
+                    return -1;
+                }
             }
+            offset = 0;
         }
+        // read for buffer size.
+        int readLen = super.read(buffer, off, size);
         if (readLen == -1) {
             eos = true;
         } else {
-            crc.update(buf, off, readLen);
+            crc.update(buffer, off, readLen);
         }
         return readLen;
     }
@@ -136,26 +172,26 @@ public class DictZipInputStream extends InflaterInputStream {
     /**
      * Read full data.
      *
-     * @param buf the buffer into which the data is read
+     * @param buffer the buffer into which the data is read
      * @exception IOException if an I/O error has occurred or the compressed input data is corrupt
      */
-    public final void readFully(final byte[] buf) throws IOException {
-        readFully(buf, 0, buf.length);
+    public final void readFully(final byte[] buffer) throws IOException {
+        readFully(buffer, 0, buffer.length);
     }
 
     /**
      * Read full data by offset/length.
      *
-     * @param buf the buffer into which the data is read
+     * @param buffer the buffer into which the data is read
      * @param off offset
-     * @param len length
+     * @param size length
      * @exception IOException if an I/O error has occurred or the compressed input data is corrupt
      */
-    public final void readFully(final byte[] buf, final int off, final int len)
+    public final void readFully(final byte[] buffer, final int off, final int size)
             throws IOException {
         int num = 0;
-        while (num < len) {
-            int count = read(buf, off + num, len - num);
+        while (num < size) {
+            int count = read(buffer, off + num, size - num);
             if (count < 0) {
                 throw new EOFException();
             }
@@ -169,7 +205,7 @@ public class DictZipInputStream extends InflaterInputStream {
      * @return header object.
      * @exception IOException if an I/O error has occurred.
      */
-    public final DictZipHeader readHeader() throws IOException {
+    private DictZipHeader readHeader() throws IOException {
         if (header == null) {
             header = DictZipHeader.readHeader(in, crc);
             crc.reset();
@@ -188,6 +224,8 @@ public class DictZipInputStream extends InflaterInputStream {
             offset = header.getOffset(next);
             long pos = header.getPosition(next);
             rain.seek(pos);
+            inf.reset();
+            eos = false;
         } else {
             throw new IOException("Illegal type of InputStream.");
         }
@@ -230,48 +268,64 @@ public class DictZipInputStream extends InflaterInputStream {
     }
 
     /**
-     * Check gzip member trailer; CRC and length.
-     * @throws IOException when CRC error or total length error.
+     * Get type of compression.
+     *
+     * @return "DZIP" or "GZIP"
+     * @throws IOException if I/O error occurred.
      */
-    private void checkTrailer() throws IOException {
-        InputStream in = this.in;
-        int num = inf.getRemaining();
-        if (num > 0) {
-            in = new SequenceInputStream(
-                    new ByteArrayInputStream(buf, len - num, num), in);
-        }
-        long val = crc.getValue();
-        long crcValue = readUInt(in);
-        if (crcValue != val) {
-            throw new IOException(MessageFormat
-                    .format("Incorrect CRC: Computed CRC = %8x / From input %8x", val, crcValue));
-        }
-        long total = inf.getTotalOut();
-        long trailerTotal = readUInt(in);
-        if (trailerTotal != total) {
-            throw new IOException(MessageFormat
-                    .format("False number of uncompressed bytes: Computed size =%d / From input %d",
-                            total, trailerTotal));
-        }
+    public String getType() throws IOException {
+        return header.getType();
+    }
+
+    /**
+     * Get length of each chunk.
+     * @return size of chunk.
+     * @throws IOException if I/O error occurred.
+     */
+    public int getChunkLength() throws IOException {
+        return header.getChunkLength();
+    }
+
+    /**
+     * Get number of chunks.
+     * @return number of chunks.
+     * @throws IOException if I/O error occurred.
+     */
+    public int getChunkCount() throws IOException {
+        return header.getChunkCount();
+    }
+
+    /**
+     * Get mtime in long.
+     * @return mtime in long.
+     * @throws IOException if I/O error occurred.
+     */
+    public long getMtime() throws IOException {
+        return header.getMtime();
+    }
+
+    /**
+     * Get Filename field if exist.
+     * @return filename or null.
+     * @throws IOException if I/O error occurred.
+     */
+    public String getFilename() throws IOException {
+        return header.getFilename();
     }
 
     /**
      * Reads GZIP member trailer.
      * @throws java.io.IOException If file I/O error
      */
-    public void readTrailer() throws IOException {
+    void readTrailer() throws IOException {
         if (in instanceof RandomAccessInputStream) {
             RandomAccessInputStream rain = (RandomAccessInputStream) in;
             compLength = rain.getLength();
             rain.seek(compLength - 8);
-        crcVal = readUInt(rain);
-        totalLength = readUInt(rain);
+            crcVal = DictZipFileUtils.readUInt(rain);
+            totalLength = DictZipFileUtils.readUInt(rain);
         } else {
             throw new IOException("Illegal type of InputStream.");
         }
     }
-
-    private long readUInt(final InputStream in) throws IOException {
-        return DictZipHeader.readUInt(in);
-    }
 }