Java tutorial
/* * Copyright 2014 Loic Merckel * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package io.uploader.drive.util; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import com.google.common.hash.HashCode; import com.google.common.hash.Hashing; import java.nio.file.*; import java.util.ArrayDeque; import java.util.Queue; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static java.nio.file.FileVisitResult.*; public class FileUtils { final static Logger logger = LoggerFactory.getLogger(FileUtils.class); private FileUtils() { super(); }; public static final String emptyMd5 = "d41d8cd98f00b204e9800998ecf8427e"; public static String getMD5(File file) throws IOException { if (file.isDirectory()) return emptyMd5; HashCode hc = com.google.common.io.Files.hash(file, Hashing.md5()); return (hc != null) ? (hc.toString()) : (null); } public static String readAllAndgetMD5(InputStream in) throws IOException { com.google.common.hash.HashingInputStream his = null; try { his = new com.google.common.hash.HashingInputStream(Hashing.md5(), in); final int bufferSize = 2097152; final ReadableByteChannel inputChannel = Channels.newChannel(his); final ByteBuffer buffer = ByteBuffer.allocateDirect(bufferSize); while (inputChannel.read(buffer) != -1) { buffer.clear(); } /* byte[] bytesBuffer = new byte[bufferSize] ; int r = his.read(bytesBuffer, 0, bufferSize) ; while (r != -1) r = his.read(bytesBuffer) ; */ HashCode hc = his.hash(); return (hc != null) ? (hc.toString()) : (null); } finally { if (his != null) his.close(); } } public enum FileFinderOption { ALL, FILE_ONLY, DIRECTORY_ONLY, } public static Queue<Path> getAllFilesPath(Path srcDir, FileFinderOption option) throws IOException { Queue<Path> queue = new ArrayDeque<Path>(); if (srcDir == null || !Files.isDirectory(srcDir)) return queue; TreePathFinder tpf = new TreePathFinder(queue, option); Files.walkFileTree(srcDir, tpf); return queue; } public static BasicFileAttributes getFileAttr(Path path) throws IOException { BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class); return attr; } private static class TreePathFinder extends SimpleFileVisitor<Path> { private final Queue<Path> filesPath; private final FileFinderOption option; public TreePathFinder(Queue<Path> filesPath, FileFinderOption option) { super(); if (filesPath == null) throw new AssertionError("TreePathFinder cannot accept null queue."); this.option = option; this.filesPath = filesPath; } @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attr) { if (option == FileFinderOption.ALL || option == FileFinderOption.FILE_ONLY) { filesPath.add(file); } return CONTINUE; } @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { if (option == FileFinderOption.ALL || option == FileFinderOption.DIRECTORY_ONLY) { filesPath.add(dir); } return CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) { return CONTINUE; } // If there is some error accessing // the file, let the user know. // If you don't override this method // and an error occurs, an IOException // is thrown. /* @Override public FileVisitResult visitFileFailed(Path file, IOException exc) { if (exc instanceof FileSystemLoopException) { logger.error("Error occurred while walking the directory to find all the files path (cycle detected: " + file + ").", exc); } else { logger.error("Error occurred while walking the directory to find all the files path.", exc); } return CONTINUE; } */ } public static class InputStreamProgressFilter extends FilterInputStream { public static interface StreamProgressCallback { public void onStreamProgress(double progress); } private final long size; private volatile long read = 0; private final StreamProgressCallback callback; protected InputStreamProgressFilter(InputStream in, long size, StreamProgressCallback callback) { super(in); if (size < 0) throw new AssertionError("The size of the stream to be minitored must be positive"); // Note: we need the size because, in.available() does not necessarily return the size (see specs). this.size = size; this.callback = callback; checkProgress(); } private double getProgress() { if (size == 0) return 1.0; return read / (double) size; } private void checkProgress() { if (callback == null) return; callback.onStreamProgress(getProgress()); } @Override public int read() throws IOException { int r = super.read(); read += r; checkProgress(); return r; } @Override public int read(byte[] b) throws IOException { int r = super.read(b); read += r; checkProgress(); return r; } @Override public int read(byte[] b, int off, int len) throws IOException { int r = super.read(b, off, len); read += r; checkProgress(); return r; } @Override public long skip(long n) throws IOException { long r = super.skip(n); read += r; checkProgress(); return r; } } public static InputStream getInputStreamWithProgressFilter( InputStreamProgressFilter.StreamProgressCallback callback, long size, Path path) throws FileNotFoundException { return getInputStreamWithProgressFilter(callback, size, new FileInputStream(path.toFile())); } public static InputStream getInputStreamWithProgressFilter( InputStreamProgressFilter.StreamProgressCallback callback, long size, InputStream input) { if (input == null) return null; InputStream in = new BufferedInputStream(new InputStreamProgressFilter(input, size, callback)); return in; } public static void saveInputStreamInFile(InputStream input, File target, boolean closeInputStream) throws IOException { if (input == null || target == null) throw new AssertionError(); FileOutputStream output = new FileOutputStream(target); try { IOUtils.copyLarge(input, output); } finally { if (output != null) output.close(); if (closeInputStream) input.close(); } } // http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java public static String humanReadableByteCount(long bytes, boolean si) { int unit = si ? 1000 : 1024; if (bytes < unit) return bytes + " B"; int exp = (int) (Math.log(bytes) / Math.log(unit)); String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i"); return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); } }