X-Git-Url: http://git.nikiroo.be/?p=fanfix.git;a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Futils%2FIOUtils.java;fp=src%2Fbe%2Fnikiroo%2Futils%2FIOUtils.java;h=e3837e17ed76c8b4bdb9274edf9524182856542a;hp=0000000000000000000000000000000000000000;hb=d46b7b96f94e88a776bcd2dfd756549ffb300cc9;hpb=c9994f27667bc421bcd448d39e55774fddf5c431 diff --git a/src/be/nikiroo/utils/IOUtils.java b/src/be/nikiroo/utils/IOUtils.java new file mode 100644 index 0000000..e3837e1 --- /dev/null +++ b/src/be/nikiroo/utils/IOUtils.java @@ -0,0 +1,476 @@ +package be.nikiroo.utils; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + +import be.nikiroo.utils.streams.MarkableFileInputStream; + +/** + * This class offer some utilities based around Streams and Files. + * + * @author niki + */ +public class IOUtils { + /** + * Write the data to the given {@link File}. + * + * @param in + * the data source + * @param target + * the target {@link File} + * + * @return the number of bytes written + * + * @throws IOException + * in case of I/O error + */ + public static long write(InputStream in, File target) throws IOException { + OutputStream out = new FileOutputStream(target); + try { + return write(in, out); + } finally { + out.close(); + } + } + + /** + * Write the data to the given {@link OutputStream}. + * + * @param in + * the data source + * @param out + * the target {@link OutputStream} + * + * @return the number of bytes written + * + * @throws IOException + * in case of I/O error + */ + public static long write(InputStream in, OutputStream out) + throws IOException { + long written = 0; + byte buffer[] = new byte[4096]; + int len = in.read(buffer); + while (len > -1) { + out.write(buffer, 0, len); + written += len; + len = in.read(buffer); + } + + return written; + } + + /** + * Recursively Add a {@link File} (which can thus be a directory, too) to a + * {@link ZipOutputStream}. + * + * @param zip + * the stream + * @param base + * the path to prepend to the ZIP info before the actual + * {@link File} path + * @param target + * the source {@link File} (which can be a directory) + * @param targetIsRoot + * FALSE if we need to add a {@link ZipEntry} for base/target, + * TRUE to add it at the root of the ZIP + * + * @throws IOException + * in case of I/O error + */ + public static void zip(ZipOutputStream zip, String base, File target, + boolean targetIsRoot) throws IOException { + if (target.isDirectory()) { + if (!targetIsRoot) { + if (base == null || base.isEmpty()) { + base = target.getName(); + } else { + base += "/" + target.getName(); + } + zip.putNextEntry(new ZipEntry(base + "/")); + } + + File[] files = target.listFiles(); + if (files != null) { + for (File file : files) { + zip(zip, base, file, false); + } + } + } else { + if (base == null || base.isEmpty()) { + base = target.getName(); + } else { + base += "/" + target.getName(); + } + zip.putNextEntry(new ZipEntry(base)); + FileInputStream in = new FileInputStream(target); + try { + IOUtils.write(in, zip); + } finally { + in.close(); + } + } + } + + /** + * Zip the given source into dest. + * + * @param src + * the source {@link File} (which can be a directory) + * @param dest + * the destination .zip file + * @param srcIsRoot + * FALSE if we need to add a {@link ZipEntry} for src, TRUE to + * add it at the root of the ZIP + * + * @throws IOException + * in case of I/O error + */ + public static void zip(File src, File dest, boolean srcIsRoot) + throws IOException { + OutputStream out = new FileOutputStream(dest); + try { + ZipOutputStream zip = new ZipOutputStream(out); + try { + IOUtils.zip(zip, "", src, srcIsRoot); + } finally { + zip.close(); + } + } finally { + out.close(); + } + } + + /** + * Unzip the given ZIP file into the target directory. + * + * @param zipFile + * the ZIP file + * @param targetDirectory + * the target directory + * + * @return the number of extracted files (not directories) + * + * @throws IOException + * in case of I/O errors + */ + public static long unzip(File zipFile, File targetDirectory) + throws IOException { + long count = 0; + + if (targetDirectory.exists() && targetDirectory.isFile()) { + throw new IOException("Cannot unzip " + zipFile + " into " + + targetDirectory + ": it is not a directory"); + } + + targetDirectory.mkdir(); + if (!targetDirectory.exists()) { + throw new IOException("Cannot create target directory " + + targetDirectory); + } + + FileInputStream in = new FileInputStream(zipFile); + try { + ZipInputStream zipStream = new ZipInputStream(in); + try { + for (ZipEntry entry = zipStream.getNextEntry(); entry != null; entry = zipStream + .getNextEntry()) { + File file = new File(targetDirectory, entry.getName()); + if (entry.isDirectory()) { + file.mkdirs(); + } else { + IOUtils.write(zipStream, file); + count++; + } + } + } finally { + zipStream.close(); + } + } finally { + in.close(); + } + + return count; + } + + /** + * Write the {@link String} content to {@link File}. + * + * @param dir + * the directory where to write the {@link File} + * @param filename + * the {@link File} name + * @param content + * the content + * + * @throws IOException + * in case of I/O error + */ + public static void writeSmallFile(File dir, String filename, String content) + throws IOException { + if (!dir.exists()) { + dir.mkdirs(); + } + + writeSmallFile(new File(dir, filename), content); + } + + /** + * Write the {@link String} content to {@link File}. + * + * @param file + * the {@link File} to write + * @param content + * the content + * + * @throws IOException + * in case of I/O error + */ + public static void writeSmallFile(File file, String content) + throws IOException { + FileOutputStream out = new FileOutputStream(file); + try { + out.write(StringUtils.getBytes(content)); + } finally { + out.close(); + } + } + + /** + * Read the whole {@link File} content into a {@link String}. + * + * @param file + * the {@link File} + * + * @return the content + * + * @throws IOException + * in case of I/O error + */ + public static String readSmallFile(File file) throws IOException { + InputStream stream = new FileInputStream(file); + try { + return readSmallStream(stream); + } finally { + stream.close(); + } + } + + /** + * Read the whole {@link InputStream} content into a {@link String}. + * + * @param stream + * the {@link InputStream} + * + * @return the content + * + * @throws IOException + * in case of I/O error + */ + public static String readSmallStream(InputStream stream) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + write(stream, out); + return out.toString("UTF-8"); + } finally { + out.close(); + } + } + + /** + * Recursively delete the given {@link File}, which may of course also be a + * directory. + *
+ * Will either silently continue or throw an exception in case of error,
+ * depending upon the parameters.
+ *
+ * @param target
+ * the target to delete
+ * @param exception
+ * TRUE to throw an {@link IOException} in case of error, FALSE
+ * to silently continue
+ *
+ * @return TRUE if all files were deleted, FALSE if an error occurred
+ *
+ * @throws IOException
+ * if an error occurred and the parameters allow an exception to
+ * be thrown
+ */
+ public static boolean deltree(File target, boolean exception)
+ throws IOException {
+ List
+ * Will silently continue in case of error.
+ *
+ * @param target
+ * the target to delete
+ *
+ * @return TRUE if all files were deleted, FALSE if an error occurred
+ */
+ public static boolean deltree(File target) {
+ return deltree(target, null).isEmpty();
+ }
+
+ /**
+ * Recursively delete the given {@link File}, which may of course also be a
+ * directory.
+ *
+ * Will collect all {@link File} that cannot be deleted in the given
+ * accumulator.
+ *
+ * @param target
+ * the target to delete
+ * @param errorAcc
+ * the accumulator to use for errors, or NULL to create a new one
+ *
+ * @return the errors accumulator
+ */
+ public static List