Mega Code Archive

 
Categories / Java / File Input Output
 

Utility class for synchronizing filesdirectories

//$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 );       }     }   } }