1 package be
.nikiroo
.utils
;
3 import java
.io
.ByteArrayOutputStream
;
5 import java
.io
.FileInputStream
;
6 import java
.io
.FileOutputStream
;
7 import java
.io
.IOException
;
8 import java
.io
.InputStream
;
9 import java
.io
.OutputStream
;
10 import java
.util
.ArrayList
;
11 import java
.util
.List
;
12 import java
.util
.zip
.ZipEntry
;
13 import java
.util
.zip
.ZipInputStream
;
14 import java
.util
.zip
.ZipOutputStream
;
16 import be
.nikiroo
.utils
.streams
.MarkableFileInputStream
;
19 * This class offer some utilities based around Streams and Files.
23 public class IOUtils
{
25 * Write the data to the given {@link File}.
30 * the target {@link File}
32 * @return the number of bytes written
35 * in case of I/O error
37 public static long write(InputStream in
, File target
) throws IOException
{
38 OutputStream out
= new FileOutputStream(target
);
40 return write(in
, out
);
47 * Write the data to the given {@link OutputStream}.
52 * the target {@link OutputStream}
54 * @return the number of bytes written
57 * in case of I/O error
59 public static long write(InputStream in
, OutputStream out
)
62 byte buffer
[] = new byte[4096];
63 int len
= in
.read(buffer
);
65 out
.write(buffer
, 0, len
);
67 len
= in
.read(buffer
);
74 * Recursively Add a {@link File} (which can thus be a directory, too) to a
75 * {@link ZipOutputStream}.
80 * the path to prepend to the ZIP info before the actual
83 * the source {@link File} (which can be a directory)
85 * FALSE if we need to add a {@link ZipEntry} for base/target,
86 * TRUE to add it at the root of the ZIP
89 * in case of I/O error
91 public static void zip(ZipOutputStream zip
, String base
, File target
,
92 boolean targetIsRoot
) throws IOException
{
93 if (target
.isDirectory()) {
95 if (base
== null || base
.isEmpty()) {
96 base
= target
.getName();
98 base
+= "/" + target
.getName();
100 zip
.putNextEntry(new ZipEntry(base
+ "/"));
103 File
[] files
= target
.listFiles();
105 for (File file
: files
) {
106 zip(zip
, base
, file
, false);
110 if (base
== null || base
.isEmpty()) {
111 base
= target
.getName();
113 base
+= "/" + target
.getName();
115 zip
.putNextEntry(new ZipEntry(base
));
116 FileInputStream in
= new FileInputStream(target
);
118 IOUtils
.write(in
, zip
);
126 * Zip the given source into dest.
129 * the source {@link File} (which can be a directory)
131 * the destination <tt>.zip</tt> file
133 * FALSE if we need to add a {@link ZipEntry} for src, TRUE to
134 * add it at the root of the ZIP
136 * @throws IOException
137 * in case of I/O error
139 public static void zip(File src
, File dest
, boolean srcIsRoot
)
141 OutputStream out
= new FileOutputStream(dest
);
143 ZipOutputStream zip
= new ZipOutputStream(out
);
145 IOUtils
.zip(zip
, "", src
, srcIsRoot
);
155 * Unzip the given ZIP file into the target directory.
159 * @param targetDirectory
160 * the target directory
162 * @return the number of extracted files (not directories)
164 * @throws IOException
165 * in case of I/O errors
167 public static long unzip(File zipFile
, File targetDirectory
)
171 if (targetDirectory
.exists() && targetDirectory
.isFile()) {
172 throw new IOException("Cannot unzip " + zipFile
+ " into "
173 + targetDirectory
+ ": it is not a directory");
176 targetDirectory
.mkdir();
177 if (!targetDirectory
.exists()) {
178 throw new IOException("Cannot create target directory "
182 FileInputStream in
= new FileInputStream(zipFile
);
184 ZipInputStream zipStream
= new ZipInputStream(in
);
186 for (ZipEntry entry
= zipStream
.getNextEntry(); entry
!= null; entry
= zipStream
188 File file
= new File(targetDirectory
, entry
.getName());
189 if (entry
.isDirectory()) {
192 IOUtils
.write(zipStream
, file
);
207 * Write the {@link String} content to {@link File}.
210 * the directory where to write the {@link File}
212 * the {@link File} name
216 * @throws IOException
217 * in case of I/O error
219 public static void writeSmallFile(File dir
, String filename
, String content
)
225 writeSmallFile(new File(dir
, filename
), content
);
229 * Write the {@link String} content to {@link File}.
232 * the {@link File} to write
236 * @throws IOException
237 * in case of I/O error
239 public static void writeSmallFile(File file
, String content
)
241 FileOutputStream out
= new FileOutputStream(file
);
243 out
.write(StringUtils
.getBytes(content
));
250 * Read the whole {@link File} content into a {@link String}.
255 * @return the content
257 * @throws IOException
258 * in case of I/O error
260 public static String
readSmallFile(File file
) throws IOException
{
261 InputStream stream
= new FileInputStream(file
);
263 return readSmallStream(stream
);
270 * Read the whole {@link InputStream} content into a {@link String}.
273 * the {@link InputStream}
275 * @return the content
277 * @throws IOException
278 * in case of I/O error
280 public static String
readSmallStream(InputStream stream
) throws IOException
{
281 ByteArrayOutputStream out
= new ByteArrayOutputStream();
284 return out
.toString("UTF-8");
291 * Recursively delete the given {@link File}, which may of course also be a
294 * Will either silently continue or throw an exception in case of error,
295 * depending upon the parameters.
298 * the target to delete
300 * TRUE to throw an {@link IOException} in case of error, FALSE
301 * to silently continue
303 * @return TRUE if all files were deleted, FALSE if an error occurred
305 * @throws IOException
306 * if an error occurred and the parameters allow an exception to
309 public static boolean deltree(File target
, boolean exception
)
311 List
<File
> list
= deltree(target
, null);
312 if (exception
&& !list
.isEmpty()) {
313 StringBuilder slist
= new StringBuilder();
314 for (File file
: list
) {
315 slist
.append("\n").append(file
.getPath());
318 throw new IOException("Cannot delete all the files from: <" //
319 + target
+ ">:" + slist
.toString());
322 return list
.isEmpty();
326 * Recursively delete the given {@link File}, which may of course also be a
329 * Will silently continue in case of error.
332 * the target to delete
334 * @return TRUE if all files were deleted, FALSE if an error occurred
336 public static boolean deltree(File target
) {
337 return deltree(target
, null).isEmpty();
341 * Recursively delete the given {@link File}, which may of course also be a
344 * Will collect all {@link File} that cannot be deleted in the given
348 * the target to delete
350 * the accumulator to use for errors, or NULL to create a new one
352 * @return the errors accumulator
354 public static List
<File
> deltree(File target
, List
<File
> errorAcc
) {
355 if (errorAcc
== null) {
356 errorAcc
= new ArrayList
<File
>();
359 File
[] files
= target
.listFiles();
361 for (File file
: files
) {
362 errorAcc
= deltree(file
, errorAcc
);
366 if (!target
.delete()) {
367 errorAcc
.add(target
);
374 * Open the resource next to the given {@link Class}.
377 * the location where to look for the resource
379 * the resource name (only the filename, no path)
381 * @return the opened resource if found, NULL if not
383 public static InputStream
openResource(
384 @SuppressWarnings("rawtypes") Class location
, String name
) {
385 String loc
= location
.getName().replace(".", "/")
386 .replaceAll("/[^/]*$", "/");
387 return openResource(loc
+ name
);
391 * Open the given /-separated resource (from the binary root).
394 * the resource name (the full path, with "/" as separator)
396 * @return the opened resource if found, NULL if not
398 public static InputStream
openResource(String name
) {
399 ClassLoader loader
= IOUtils
.class.getClassLoader();
400 if (loader
== null) {
401 loader
= ClassLoader
.getSystemClassLoader();
404 return loader
.getResourceAsStream(name
);
408 * Return a resetable {@link InputStream} from this stream, and reset it.
412 * @return the resetable stream, which <b>may</b> be the same
414 * @throws IOException
415 * in case of I/O error
417 public static InputStream
forceResetableStream(InputStream in
)
419 boolean resetable
= in
.markSupported();
423 } catch (IOException e
) {
432 final File tmp
= File
.createTempFile(".tmp-stream.", ".tmp");
437 return new MarkableFileInputStream(tmp
) {
439 public void close() throws IOException
{
447 } catch (IOException e
) {
454 * Convert the {@link InputStream} into a byte array.
461 * @throws IOException
462 * in case of I/O error
464 public static byte[] toByteArray(InputStream in
) throws IOException
{
465 ByteArrayOutputStream out
= new ByteArrayOutputStream();
468 return out
.toByteArray();
475 * Convert the {@link File} into a byte array.
478 * the input {@link File}
482 * @throws IOException
483 * in case of I/O error
485 public static byte[] toByteArray(File file
) throws IOException
{
486 FileInputStream fis
= new FileInputStream(file
);
488 return toByteArray(fis
);