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 041 /** 042 * Creates a new input stream that decompresses Deflate-compressed data 043 * from the specified input stream. 044 * 045 * @param inputStream where to read the compressed data 046 * 047 */ 048 public DeflateCompressorInputStream(InputStream inputStream) { 049 this(inputStream, new DeflateParameters()); 050 } 051 052 /** 053 * Creates a new input stream that decompresses Deflate-compressed data 054 * from the specified input stream. 055 * 056 * @param inputStream where to read the compressed data 057 * @param parameters parameters 058 */ 059 public DeflateCompressorInputStream(InputStream inputStream, 060 DeflateParameters parameters) { 061 in = new InflaterInputStream(inputStream, new Inflater(!parameters.withZlibHeader())); 062 } 063 064 /** {@inheritDoc} */ 065 @Override 066 public int read() throws IOException { 067 int ret = in.read(); 068 count(ret == -1 ? 0 : 1); 069 return ret; 070 } 071 072 /** {@inheritDoc} */ 073 @Override 074 public int read(byte[] buf, int off, int len) throws IOException { 075 int ret = in.read(buf, off, len); 076 count(ret); 077 return ret; 078 } 079 080 /** {@inheritDoc} */ 081 @Override 082 public long skip(long n) throws IOException { 083 return in.skip(n); 084 } 085 086 /** {@inheritDoc} */ 087 @Override 088 public int available() throws IOException { 089 return in.available(); 090 } 091 092 /** {@inheritDoc} */ 093 @Override 094 public void close() throws IOException { 095 in.close(); 096 } 097 098 /** 099 * Checks if the signature matches what is expected for a zlib / deflated file 100 * with the zlib header. 101 * 102 * @param signature 103 * the bytes to check 104 * @param length 105 * the number of bytes to check 106 * @return true, if this stream is zlib / deflate compressed with a header 107 * stream, false otherwise 108 * 109 * @since 1.10 110 */ 111 public static boolean matches(byte[] signature, int length) { 112 return length > 3 && signature[0] == MAGIC_1 && ( 113 signature[1] == (byte) MAGIC_2a || 114 signature[1] == (byte) MAGIC_2b || 115 signature[1] == (byte) MAGIC_2c || 116 signature[1] == (byte) MAGIC_2d); 117 } 118}