package jef.tools; import java.io.File; /** * 描述文件夹拷贝策略,除了默认提供的几个策略外,一般供应用继承。 * * @Date 2011-5-9 */ public class CopyStrategy { /** * 复制策略,不覆盖已存在的文件(默认) 1.跳过.开头的文件夹和文件 2.不覆盖已存在的文件 */ public static final CopyStrategy NO_OVERWRITE = new CopyStrategy(); /** * 复制策略,总是覆盖已存在的文件: 1.跳过.开头的文件夹和文件 2.总是覆盖已存在的文件 */ public static final CopyStrategy ALLWAYS_OVERWRITE = new CopyStrategy() { public boolean canOverWritten(File file, File target) { return true; } }; /** * 复制策略,当文件内容不同时 覆盖已存在的文件: 1.跳过.开头的文件夹和文件 2.当文件不同时覆盖已存在的文件(根据文件大小和CRC判断) */ public static final CopyStrategy OVERWRITE_IF_DIFFERENT = new CopyStrategy() { private FileComparator comparator=FileComparator.LENGTH_SKIP; public boolean canOverWritten(File file, File target) { if (!file.exists()) return false; if (!target.exists()) return true; return !comparator.equals(file,target); } }; /** * 供子类覆盖,描述拷贝行为: 是否拷贝该文件夹的内容 * * @param file * 源文件夹 * @param newFile * 目标文件夹 * @return true表示该文件夹需要拷贝,false表示不拷贝 */ public boolean processFolder(File file, File newFile) { if (file.getName().startsWith(".")) return false; return true; } /** * 供子类覆盖,描述拷贝行为: 给出目标文件名 * * @param file * 源文件 * @param targetFolder * 目标文件夹 * @return File,要拷贝的目标文件,null将不拷贝源文件。 */ public File getTargetFile(File file, File targetFolder) { File target= new File(targetFolder, file.getName()); return target; } /** * 供子类覆盖,描述拷贝行为: 目标文件已经存在时,可否覆盖 * * @param source * 源文件 * @param target * 目标文件,注意一定是文件 * @return true表示允许覆盖目标文件,false反之 */ public boolean canOverWritten(File source, File target) { return false; } /** * 如果源是一个文件而目标是一个目录,是否允许将源复制到目录下。 * * @return true表示允许;false表示不允许,此时将抛出异常。 */ public boolean allowFileIntoFolder() { return true; } /** * 返回true,表示是移动文件,源文件将被删除 * @return */ public boolean isMove() { return false; } /** * 该策略用于合并两个文件夹。 * <li>源目录有而目标目录没有的文件,移动/复制到目标目录</li> * <li>两边相同的文件,删除源目录下的(move模式下)</li> * <li>两边不同的文件,不作操作,打印出文件名</li> */ public static class MergeStrategy extends CopyStrategy { private FileComparator comparator; private int normalCount; //不冲突的文件数,(在源有而目标没有的文件)复制。 private int duplicateCount; //两边完全相同的文件数。 private int conflictCount; //两边冲突的文件数 private int deleteSuccessCount;//在两边完全相同时,如果是move指令,则会删除源文件夹中的重复文件,这里记录成功删除的数量 private int mergeFailure; //在源是目录而目标是文件,或者源为文件目标为目录,此时无法实现合并 private boolean isMove=true; /** * 构造 */ public MergeStrategy() { this(FileComparator.LENGTH_SKIP); } /** * 构造 * @param compare 传入一个指定的文件比较器 */ public MergeStrategy(FileComparator compare) { super(); this.comparator = compare; } /** * 设置move模式 * @param isMove */ public void setMove(boolean isMove) { this.isMove = isMove; } @Override public File getTargetFile(File file, File targetFolder) { File f = new File(targetFolder, file.getName()); if (f.isFile()) { if(file.isDirectory()){ System.out.println("the target " + f.getPath() + " has exist, and is not folder."); mergeFailure++; return null; } if (comparator.equals(file, f)) { //源于目标相同文件 duplicateCount++; if(isMove){ //Move的场合直接删除源文件。 if (file.delete()) { deleteSuccessCount++; } else { System.out.println("删除" + file.getAbsolutePath() + "失败."); } } return null;//该文件无需复制 } else { //源和目标不同文件 System.out.println("文件" + file.getAbsolutePath() + " 已经存在不同版本!!(内容不同)"); conflictCount++; return null;//版本不同,不覆盖 } }else if (f.exists() && file.isFile()){ System.out.println("Target is directory and source is a file:"+file.getAbsolutePath()); mergeFailure++; return null; }else{ normalCount++; } return f; } @Override public boolean isMove() { return isMove; } public boolean canOverWritten(File file, File target) { throw new IllegalArgumentException(); } /** * 不冲突的文件数(在源有而目标没有的文件) * @return */ public int getNormalCount() { return normalCount; } /** * * @return 两边完全相同的文件数。 */ public int getDuplicateCount() { return duplicateCount; } /** * @return 两边冲突的文件数 */ public int getConflictCount() { return conflictCount; } /** * 在两边完全相同时,如果是move指令,成功删除的文件数 * @return */ public int getDeleteSuccessCount() { return deleteSuccessCount; } public String getSummary(){ StringBuilder sb=new StringBuilder(); sb.append(isMove?"Moved:":"Copyed:").append(this.normalCount).append("\r\n"); sb.append("Duplicate:").append(this.duplicateCount); if(isMove){ sb.append(" Deleted:").append(this.deleteSuccessCount); } sb.append(" MergeFailure:").append(this.mergeFailure); sb.append("\r\n"); sb.append("ConflictFiles:").append(this.conflictCount); return sb.toString(); } }; }