Version 4.0.0: java.awt dependencies move
[nikiroo-utils.git] / src / be / nikiroo / utils / IOUtils.java
1 package be.nikiroo.utils;
2
3 import java.io.BufferedReader;
4 import java.io.ByteArrayOutputStream;
5 import java.io.File;
6 import java.io.FileInputStream;
7 import java.io.FileOutputStream;
8 import java.io.FileWriter;
9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.io.InputStreamReader;
12 import java.io.OutputStream;
13 import java.util.zip.ZipEntry;
14 import java.util.zip.ZipOutputStream;
15
16 /**
17 * This class offer some utilities based around Streams.
18 *
19 * @author niki
20 */
21 public class IOUtils {
22 /**
23 * Write the data to the given {@link File}.
24 *
25 * @param in
26 * the data source
27 * @param target
28 * the target {@link File}
29 *
30 * @throws IOException
31 * in case of I/O error
32 */
33 public static void write(InputStream in, File target) throws IOException {
34 OutputStream out = new FileOutputStream(target);
35 try {
36 write(in, out);
37 } finally {
38 out.close();
39 }
40 }
41
42 /**
43 * Write the data to the given {@link OutputStream}.
44 *
45 * @param in
46 * the data source
47 * @param out
48 * the target {@link OutputStream}
49 *
50 * @throws IOException
51 * in case of I/O error
52 */
53 public static void write(InputStream in, OutputStream out)
54 throws IOException {
55 byte buffer[] = new byte[4069];
56 for (int len = 0; (len = in.read(buffer)) > 0;) {
57 out.write(buffer, 0, len);
58 }
59 }
60
61 /**
62 * Recursively Add a {@link File} (which can thus be a directory, too) to a
63 * {@link ZipOutputStream}.
64 *
65 * @param zip
66 * the stream
67 * @param base
68 * the path to prepend to the ZIP info before the actual
69 * {@link File} path
70 * @param target
71 * the source {@link File} (which can be a directory)
72 * @param targetIsRoot
73 * FALSE if we need to add a {@link ZipEntry} for base/target,
74 * TRUE to add it at the root of the ZIP
75 *
76 * @throws IOException
77 * in case of I/O error
78 */
79 public static void zip(ZipOutputStream zip, String base, File target,
80 boolean targetIsRoot) throws IOException {
81 if (target.isDirectory()) {
82 if (!targetIsRoot) {
83 if (base == null || base.isEmpty()) {
84 base = target.getName();
85 } else {
86 base += "/" + target.getName();
87 }
88 zip.putNextEntry(new ZipEntry(base + "/"));
89 }
90 for (File file : target.listFiles()) {
91 zip(zip, base, file, false);
92 }
93 } else {
94 if (base == null || base.isEmpty()) {
95 base = target.getName();
96 } else {
97 base += "/" + target.getName();
98 }
99 zip.putNextEntry(new ZipEntry(base));
100 FileInputStream in = new FileInputStream(target);
101 try {
102 IOUtils.write(in, zip);
103 } finally {
104 in.close();
105 }
106 }
107 }
108
109 /**
110 * Zip the given source into dest.
111 *
112 * @param src
113 * the source {@link File} (which can be a directory)
114 * @param dest
115 * the destination <tt>.zip</tt> file
116 * @param srcIsRoot
117 * FALSE if we need to add a {@link ZipEntry} for src, TRUE to
118 * add it at the root of the ZIP
119 *
120 * @throws IOException
121 * in case of I/O error
122 */
123 public static void zip(File src, File dest, boolean srcIsRoot)
124 throws IOException {
125 OutputStream out = new FileOutputStream(dest);
126 try {
127 ZipOutputStream zip = new ZipOutputStream(out);
128 try {
129 IOUtils.zip(zip, "", src, srcIsRoot);
130 } finally {
131 zip.close();
132 }
133 } finally {
134 out.close();
135 }
136 }
137
138 /**
139 * Write the {@link String} content to {@link File}.
140 *
141 * @param dir
142 * the directory where to write the {@link File}
143 * @param filename
144 * the {@link File} name
145 * @param content
146 * the content
147 *
148 * @throws IOException
149 * in case of I/O error
150 */
151 public static void writeSmallFile(File dir, String filename, String content)
152 throws IOException {
153 if (!dir.exists()) {
154 dir.mkdirs();
155 }
156
157 FileWriter writerVersion = new FileWriter(new File(dir, filename));
158 try {
159 writerVersion.write(content);
160 } finally {
161 writerVersion.close();
162 }
163 }
164
165 /**
166 * Read the whole {@link File} content into a {@link String}.
167 *
168 * @param file
169 * the {@link File}
170 *
171 * @return the content
172 *
173 * @throws IOException
174 * in case of I/O error
175 */
176 public static String readSmallFile(File file) throws IOException {
177 InputStream stream = new FileInputStream(file);
178 try {
179 return readSmallStream(stream);
180 } finally {
181 stream.close();
182 }
183 }
184
185 /**
186 * Read the whole {@link InputStream} content into a {@link String}.
187 *
188 * @param stream
189 * the {@link InputStream}
190 *
191 * @return the content
192 *
193 * @throws IOException
194 * in case of I/O error
195 */
196 public static String readSmallStream(InputStream stream) throws IOException {
197 // do NOT close the reader, or the related stream will be closed, too
198 // reader.close();
199 BufferedReader reader = new BufferedReader(
200 new InputStreamReader(stream));
201
202 StringBuilder builder = new StringBuilder();
203 for (String line = reader.readLine(); line != null; line = reader
204 .readLine()) {
205 builder.append(line);
206 builder.append("\n");
207 }
208
209 return builder.toString();
210 }
211
212 /**
213 * Recursively delete the given {@link File}, which may of course also be a
214 * directory.
215 * <p>
216 * Will silently continue in case of error.
217 *
218 * @param target
219 * the target to delete
220 */
221 public static void deltree(File target) {
222 File[] files = target.listFiles();
223 if (files != null) {
224 for (File file : files) {
225 deltree(file);
226 }
227 }
228
229 if (!target.delete()) {
230 System.err.println("Cannot delete: " + target.getAbsolutePath());
231 }
232 }
233
234 /**
235 * Open the given /-separated resource (from the binary root).
236 *
237 * @param name
238 * the resource name
239 *
240 * @return the opened resource if found, NLL if not
241 */
242 public static InputStream openResource(String name) {
243 ClassLoader loader = IOUtils.class.getClassLoader();
244 if (loader == null) {
245 loader = ClassLoader.getSystemClassLoader();
246 }
247
248 return loader.getResourceAsStream(name);
249 }
250
251 /**
252 * Return a resetable {@link InputStream} from this stream, and reset it.
253 *
254 * @param in
255 * the input stream
256 * @return the resetable stream, which <b>may</b> be the same
257 *
258 * @throws IOException
259 * in case of I/O error
260 */
261 public static InputStream forceResetableStream(InputStream in)
262 throws IOException {
263 MarkableFileInputStream tmpIn = null;
264 File tmp = null;
265
266 boolean resetable = in.markSupported();
267 if (resetable) {
268 try {
269 in.reset();
270 } catch (IOException e) {
271 resetable = false;
272 }
273 }
274
275 if (resetable) {
276 return in;
277 }
278
279 tmp = File.createTempFile(".tmp-stream", ".tmp");
280 try {
281 write(in, tmp);
282 tmpIn = new MarkableFileInputStream(new FileInputStream(tmp));
283 return tmpIn;
284 } finally {
285 try {
286 if (tmpIn != null) {
287 tmpIn.close();
288 }
289 } finally {
290 tmp.delete();
291 }
292 }
293 }
294
295 /**
296 * Convert the {@link InputStream} into a byte array.
297 *
298 * @param in
299 * the input stream
300 *
301 * @return the array
302 *
303 * @throws IOException
304 * in case of I/O error
305 */
306 public static byte[] toByteArray(InputStream in) throws IOException {
307 ByteArrayOutputStream out = new ByteArrayOutputStream();
308 write(in, out);
309
310 byte[] array = out.toByteArray();
311 out.close();
312
313 return array;
314 }
315 }