import java.io.*;


/**

 * 文件操作工具集。包括文件、目录树的拷贝、删除、移动、查找等工具函数。

 * @author InternetTeam3

 * @version 1.0

 */

public class FileTool{


  /**

   * 复制单个文件。源和目标必须都是文件,不能是目录。

   * @param src 源文件。

   * @param dest 目标文件。

   * @param cover true表示如果目标文件存在则覆盖,false表示如果目标文件存在则抛出异常。

   */

  public static void copy(File src, File dest, boolean cover)

                                                          throws IOException {

    FileInputStream fis = new FileInputStream(src);

    FileOutputStream fos = new FileOutputStream(dest);

    byte[] buf = new byte[1024];

    try {

      int i;

      while ((i=fis.read(buf))>=0) {

        fos.write(buf,0,i);

      }

    } finally {

      try {fis.close();} catch (Exception ex){}

      try {fos.close();} catch (Exception ex){}

    }

  }


  /**

   * 复制目录树。

   * 如果源和目标都是目录,则将源目录里的文件拷贝到目标目录里;

   * 如果源是文件目标是目录,则将源拷贝到目标目录里面;

   * 如果源是目录而目标是文件,则抛异常;

   * 如果源和目标都是文件,则用源文件覆盖目标文件;

   * 如果源是文件而目标不存在,则在目标位置创建文件;

   * 如果源是目录而目标不存在,则以目标名称建立目录,并将源目录里内容拷贝至目标目录下。

   * 如果源不存在,则抛异常。

   * @param src 源文件或目录。

   * @param dest 目的文件或目录。

   * @param cover 目的文件存在是否覆盖,若是false则遇到该覆盖文件时将抛异常。

   */

  public static void copytree(File src,File dest,boolean cover)

                                                        throws IOException {

    if (src.isFile()) {

      copy(src,dest,cover);

    } else { // src是目录或不存在

      File[] children = src.listFiles(); //若src不存在这里会抛异常

      for (int i=0;i<children.length;i++) {

        File f = new File(dest,children[i].getName());

        if (children[i].isDirectory()) { //对于src的每个子目录

          f.mkdirs(); //创建目标子目录,如果已经存在则会忽略

          copytree(children[i],f,cover); //递归

        } else { //对于src下每个文件

          copy(children[i],f,cover);

        }

      }

    }

  }


  /**

   * 复制目录树。

   * 如果源和目标都是目录,则将源目录里的文件拷贝到目标目录里;

   * 如果源是文件目标是目录则将源拷贝到目标目录里面;

   * 如果源是目录而目标是文件,则抛异常;

   * 如果源和目标都是文件则用源文件覆盖目标文件;

   * 如果源是文件而目标不存在则在目标位置创建文件;

   * 如果源是目录而目标不存在则在以目标名称建立目录并将源目录里内容拷贝至目标目录下。

   * 如果源不存在则抛异常。

   * @param src 源文件或目录。

   * @param dest 目的文件或目录。

   * @param cover 目的文件存在是否覆盖,若是false则遇到该覆盖文件时将抛异常。

   */

  public static void movetree(File src, File dest, boolean cover) throws IOException {

    copytree(src,dest,cover);

    deltree(src);

  }


  /**

   * 删除文件或整个目录树。

   * @param f 文件或目录。

   */

  public static void deltree(File f) {

    File[] children = f.listFiles();

    if (children!=null && children.length!=0) {

      for (int i=0;i<children.length;i++) {

        deltree(children[i]);

      }

    }

    f.delete();

  }


  /**

   * 在一个目录及其子目录下查找符合条件的文件或目录。

   * @param filter 文件过滤条件。该接口的accept方法如果返回true则中止查找,否则继续查找,

   * 对文件的处理请在该接口的accept()方法里完成。

   * @param root 查找开始的位置。

   * @return 是否找到。

   */

  public static boolean find(File root, FileFilter filter) {

    if (filter.accept(root)) {

      return true;

    } else {

      File[] children = root.listFiles();

      if (children==null || children.length==0) {

        return false;

      } else {

        for (int i=0;i<children.length;i++) {

          if (find(children[i],filter)) {

            return true;

          }

        }

        return false;

      }

    }

  }

}