001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.commons.compress.compressors.deflate; 020 021import java.io.IOException; 022import java.io.InputStream; 023import java.util.zip.Inflater; 024import java.util.zip.InflaterInputStream; 025 026import org.apache.commons.compress.compressors.CompressorInputStream; 027 028/** 029 * Deflate decompressor. 030 * @since 1.9 031 */ 032public class DeflateCompressorInputStream extends CompressorInputStream { 033 private static final int MAGIC_1 = 0x78; 034 private static final int MAGIC_2a = 0x01; 035 private static final int MAGIC_2b = 0x5e; 036 private static final int MAGIC_2c = 0x9c; 037 private static final int MAGIC_2d = 0xda; 038 039 private final InputStream in; 040 private final Inflater inflater; 041 042 /** 043 * Creates a new input stream that decompresses Deflate-compressed data 044 * from the specified input stream. 045 * 046 * @param inputStream where to read the compressed data 047 * 048 */ 049 public DeflateCompressorInputStream(final InputStream inputStream) { 050 this(inputStream, new DeflateParameters()); 051 } 052 053 /** 054 * Creates a new input stream that decompresses Deflate-compressed data 055 * from the specified input stream. 056 * 057 * @param inputStream where to read the compressed data 058 * @param parameters parameters 059 */ 060 public DeflateCompressorInputStream(final InputStream inputStream, 061 final DeflateParameters parameters) { 062 inflater = new Inflater(!parameters.withZlibHeader()); 063 in = new InflaterInputStream(inputStream, inflater); 064 } 065 066 /** {@inheritDoc} */ 067 @Override 068 public int read() throws IOException { 069 final int ret = in.read(); 070 count(ret == -1 ? 0 : 1); 071 return ret; 072 } 073 074 /** {@inheritDoc} */ 075 @Override 076 public int read(final byte[] buf, final int off, final int len) throws IOException { 077 final int ret = in.read(buf, off, len); 078 count(ret); 079 return ret; 080 } 081 082 /** {@inheritDoc} */ 083 @Override 084 public long skip(final long n) throws IOException { 085 return in.skip(n); 086 } 087 088 /** {@inheritDoc} */ 089 @Override 090 public int available() throws IOException { 091 return in.available(); 092 } 093 094 /** {@inheritDoc} */ 095 @Override 096 public void close() throws IOException { 097 try { 098 in.close(); 099 } finally { 100 inflater.end(); 101 } 102 } 103 104 /** 105 * Checks if the signature matches what is expected for a zlib / deflated file 106 * with the zlib header. 107 * 108 * @param signature 109 * the bytes to check 110 * @param length 111 * the number of bytes to check 112 * @return true, if this stream is zlib / deflate compressed with a header 113 * stream, false otherwise 114 * 115 * @since 1.10 116 */ 117 public static boolean matches(final byte[] signature, final int length) { 118 return length > 3 && signature[0] == MAGIC_1 && ( 119 signature[1] == (byte) MAGIC_2a || 120 signature[1] == (byte) MAGIC_2b || 121 signature[1] == (byte) MAGIC_2c || 122 signature[1] == (byte) MAGIC_2d); 123 } 124}