Java tutorial
//$Id: FileHelper.java 15522 2008-11-05 20:06:43Z hardy.ferentschik $ //Revised from hibernate search util import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel; import java.util.Arrays; import java.util.HashSet; import java.util.Set; /** * Utility class for synchronizing files/directories. * * @author Emmanuel Bernard * @author Sanne Grinovero * @author Hardy Ferentschik */ public abstract class FileHelper { private static final int FAT_PRECISION = 2000; public static final long DEFAULT_COPY_BUFFER_SIZE = 16 * 1024 * 1024; // 16 MB public static boolean areInSync(File source, File destination) throws IOException { if (source.isDirectory()) { if (!destination.exists()) { return false; } else if (!destination.isDirectory()) { throw new IOException("Source and Destination not of the same type:" + source.getCanonicalPath() + " , " + destination.getCanonicalPath()); } String[] sources = source.list(); Set<String> srcNames = new HashSet<String>(Arrays.asList(sources)); String[] dests = destination.list(); // check for files in destination and not in source for (String fileName : dests) { if (!srcNames.contains(fileName)) { return false; } } boolean inSync = true; for (String fileName : sources) { File srcFile = new File(source, fileName); File destFile = new File(destination, fileName); if (!areInSync(srcFile, destFile)) { inSync = false; break; } } return inSync; } else { if (destination.exists() && destination.isFile()) { long sts = source.lastModified() / FAT_PRECISION; long dts = destination.lastModified() / FAT_PRECISION; return sts == dts; } else { return false; } } } public static void synchronize(File source, File destination, boolean smart) throws IOException { synchronize(source, destination, smart, DEFAULT_COPY_BUFFER_SIZE); } public static void synchronize(File source, File destination, boolean smart, long chunkSize) throws IOException { if (chunkSize <= 0) { System.out.println("Chunk size must be positive: using default value."); chunkSize = DEFAULT_COPY_BUFFER_SIZE; } if (source.isDirectory()) { if (!destination.exists()) { if (!destination.mkdirs()) { throw new IOException("Could not create path " + destination); } } else if (!destination.isDirectory()) { throw new IOException("Source and Destination not of the same type:" + source.getCanonicalPath() + " , " + destination.getCanonicalPath()); } String[] sources = source.list(); Set<String> srcNames = new HashSet<String>(Arrays.asList(sources)); String[] dests = destination.list(); //delete files not present in source for (String fileName : dests) { if (!srcNames.contains(fileName)) { delete(new File(destination, fileName)); } } //copy each file from source for (String fileName : sources) { File srcFile = new File(source, fileName); File destFile = new File(destination, fileName); synchronize(srcFile, destFile, smart, chunkSize); } } else { if (destination.exists() && destination.isDirectory()) { delete(destination); } if (destination.exists()) { long sts = source.lastModified() / FAT_PRECISION; long dts = destination.lastModified() / FAT_PRECISION; //do not copy if smart and same timestamp and same length if (!smart || sts == 0 || sts != dts || source.length() != destination.length()) { copyFile(source, destination, chunkSize); } } else { copyFile(source, destination, chunkSize); } } } private static void copyFile(File srcFile, File destFile, long chunkSize) throws IOException { FileInputStream is = null; FileOutputStream os = null; try { is = new FileInputStream(srcFile); FileChannel iChannel = is.getChannel(); os = new FileOutputStream(destFile, false); FileChannel oChannel = os.getChannel(); long doneBytes = 0L; long todoBytes = srcFile.length(); while (todoBytes != 0L) { long iterationBytes = Math.min(todoBytes, chunkSize); long transferredLength = oChannel.transferFrom(iChannel, doneBytes, iterationBytes); if (iterationBytes != transferredLength) { throw new IOException("Error during file transfer: expected " + iterationBytes + " bytes, only " + transferredLength + " bytes copied."); } doneBytes += transferredLength; todoBytes -= transferredLength; } } finally { if (is != null) { is.close(); } if (os != null) { os.close(); } } boolean successTimestampOp = destFile.setLastModified(srcFile.lastModified()); if (!successTimestampOp) { System.out.println("Could not change timestamp for {}. Index synchronization may be slow. " + destFile); } } public static void delete(File file) { if (file.isDirectory()) { for (File subFile : file.listFiles()) { delete(subFile); } } if (file.exists()) { if (!file.delete()) { System.out.println("Could not delete {}" + file); } } } }