1 package org.opentrafficsim.base.compressedfiles;
2
3 import java.io.BufferedInputStream;
4 import java.io.Closeable;
5 import java.io.File;
6 import java.io.FileInputStream;
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.util.zip.GZIPInputStream;
10 import java.util.zip.ZipFile;
11
12 import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
13
14
15
16
17
18
19
20
21
22
23
24
25 public final class Reader
26 {
27
28
29
30 private Reader()
31 {
32
33 }
34
35
36
37
38
39
40
41
42 public static InputStream createInputStream(final String fileName, final CompressionType compressionType) throws IOException
43 {
44 CompressionType useCompressionType =
45 CompressionType.AUTODETECT.equals(compressionType) ? autoDetectCompressionType(fileName) : compressionType;
46 switch (useCompressionType)
47 {
48 case AUTODETECT:
49 throw new IOException("Cannot happen");
50
51 case BZIP2:
52
53 return new BZip2CompressorInputStream(new FileInputStream(fileName), true);
54
55 case GZIP:
56 return new GZIPInputStream(new FileInputStream(fileName));
57
58 case NONE:
59 return new FileInputStream(fileName);
60
61 case ZIP:
62 {
63 ZipFile zipFile = new ZipFile(fileName);
64 return new ZipInputStream(zipFile, zipFile.getInputStream(zipFile.entries().nextElement()));
65 }
66
67 default:
68
69 throw new IOException("Don't know how to create input stream for compression type " + compressionType);
70
71 }
72 }
73
74
75
76
77
78
79
80 public static InputStream createInputStream(final String fileName) throws IOException
81 {
82 return createInputStream(fileName, CompressionType.AUTODETECT);
83 }
84
85
86
87
88
89
90
91
92
93
94
95
96 public static CompressionType autoDetectCompressionType(final String fileName) throws IOException
97 {
98 final int signatureSize = 10;
99 BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(new File(fileName)));
100 byte[] signature = new byte[signatureSize];
101 bufferedInputStream.read(signature);
102 bufferedInputStream.close();
103
104
105
106
107 if (isGZipCompressed(signature))
108 {
109 return CompressionType.GZIP;
110 }
111 else if (isBZipCompressed(signature))
112 {
113 return CompressionType.BZIP2;
114 }
115 else if (isZipCompressed(signature))
116 {
117 return CompressionType.ZIP;
118 }
119 return CompressionType.NONE;
120 }
121
122
123
124
125
126
127
128
129
130
131
132 public static boolean isGZipCompressed(final byte[] bytes) throws IOException
133 {
134 return (bytes[0] == (byte) (GZIPInputStream.GZIP_MAGIC)) && (bytes[1] == (byte) (GZIPInputStream.GZIP_MAGIC >> 8));
135 }
136
137
138
139
140
141
142 private static boolean isBZipCompressed(final byte[] bytes)
143 {
144 return bytes[0] == 'B' && bytes[1] == 'Z' && (bytes[2] == 'h' || bytes[2] == '0') && Character.isDigit(bytes[3])
145 && bytes[4] == 0x31 && bytes[5] == 0x41 && bytes[6] == 0x59 && bytes[7] == 0x26 && bytes[8] == 0x53
146 && bytes[9] == 0x59;
147 }
148
149
150
151
152
153
154
155 private static boolean isZipCompressed(final byte[] bytes)
156 {
157 if (bytes[0] != 0x50 || bytes[1] != 0x4b)
158 {
159 return false;
160 }
161 return 0x03 == bytes[2] && 0x04 == bytes[3] || 0x05 == bytes[2] && 0x06 == bytes[3]
162 || 0x07 == bytes[2] && 0x08 == bytes[3];
163 }
164
165
166
167
168 static class ZipInputStream extends InputStream implements Closeable
169 {
170
171 private final ZipFile zipFile;
172
173
174 private final InputStream inputStream;
175
176
177
178
179
180
181 ZipInputStream(final ZipFile zipFile, final InputStream inputStream)
182 {
183 this.inputStream = inputStream;
184 this.zipFile = zipFile;
185 }
186
187
188
189
190
191 @Override
192 public void close() throws IOException
193 {
194 super.close();
195 this.zipFile.close();
196 }
197
198
199 @Override
200 public int read() throws IOException
201 {
202 return this.inputStream.read();
203 }
204
205
206 @Override
207 public String toString()
208 {
209 return "ZipInputStream [zipFile=" + this.zipFile + ", inputStream=" + this.inputStream + "]";
210 }
211
212 }
213
214 }