【任务描述】
    编写一个模拟文件管理器的程序,实现控制台对文件和文件夹的管理操作。此程序中,当用户输入指令 1 时,代表“指定关键字检索文件”,此时需要用户输入检索的目录和关键字,系统在用户指定的目录下检索出文件名中包含关键字的文件,并将其绝对路径展示出来。指令 2 代表“指定后缀名检索文件”,此时需要用户输入检索的目录和后缀名(可输入由逗号分割的多个后缀名,来实现同时对不同后缀名文件的搜索),系统在用户指定的目录下检索出指定后缀名的文件,并将其绝对路径展示出来。指令 3 代表“复制文件/目录”,此时需要用户输入源目录和目标目录,程序执行后会将源目录下的内容复制到目标目录下。指令 4 代表“退出”,即退出系统。

    【实现思路】**

    1. 根据任务介绍和运行结果分析可知,首先需要创建一个文件管理器类。可以在类中使用 while 循环实现控制台中操作指令的多次输入,并使用 switch 语句根据控制台输入的操作指令来判断执行什么操作。
    2. 执行指令 1 时,代表指定关键词引索文件,即在目录下查找包含关键词的文件。执行时先要从控制台获取目录和关键字,然后将其传到后台的方法中,后台可将传入的关键字利用过滤器制定成“规则”,通过递归的方式遍历文件夹,在每个子文件夹下调用过滤镜,来获取符合规则的文件路径,并将集合返回,最后打印出来。
    3. 执行指令 2 时,代表指定后缀名检索文件,即在目录下查找名称结尾是指定后缀的文件。执行时可以先从控制台获取目录和后缀名,然将后缀名拆分成数组,并将数组和目录传到后台方法中。后台可用过滤器将后缀名数组循环遍历,制定成“规则”,通过递归的方式遍历文件夹,在每个子文件夹下调用过滤器,来获取符合规则的文件路径的集合,并将集合返回,最后打印出来。
    4. 执行指令 3 时,代表将源目录的内容复制到目标目录中。执行时可以先从控制台获取源目录和目标目录,然后将其传入后台。后台主要时通过递归的方法执行文件和文件夹复制的。每次调用此方法时,首先会获取当前目录下的文件和文件夹列表,然后循环列表并判断当前元素是文件还是文件夹。如果是文件夹,就利用 File 类的 mkdirs()方法在目标目录中创建此文件夹,再调用自身;如果是文件,由于不一定是纯文本文件,所以可以采用字节流将文件写入到目标目录。
    5. 执行指令 4 时,执行退出该程序的操作,该操作可以通过 System.exit(0)来实现。

    【实现代码】
    1、定义 DocumentManager 类,具体如下所示。

    1. import java.awt.List;
    2. import java.io.File;
    3. import java.util.ArrayList;
    4. import java.util.Scanner;
    5. public class DocumentManager {
    6. public static void main(String[] args) throws Exception{
    7. Scanner sc = new Scanner(System.in);
    8. System.out.println("==1:指定关键字检索文件 2:指定后缀名检索文件 3:复制文件/目录 4:退出==");
    9. while (true) {
    10. System.out.println("请输入指令");
    11. int command = sc.nextInt();
    12. switch (command) {
    13. case 1:
    14. searchByKeyWord(); //指定关键字检索文件
    15. break;
    16. case 2:
    17. searchBusuffix(); //指定后缀名检索文件
    18. break;
    19. case 3:
    20. copyDirectory(); //复制文件/目录
    21. break;
    22. case 4:
    23. exit(); //退出
    24. break;
    25. default:
    26. break;
    27. }
    28. }
    29. }
    30. //***********1.指定关键字检索文件***********
    31. private static void searchByKeyWord() {
    32. Scanner sc = new Scanner(System.in);
    33. System.out.println("请输入要检索的目录位置:");
    34. String path = sc.next(); //从控制台获取路径
    35. File file = new File(path);
    36. if (!file.exists() || !file.isDirectory()) {
    37. System.out.println(path + "(不是有效目录)");
    38. return;
    39. }
    40. System.out.println("请输入搜索关键词:");
    41. String key = sc.next(); //获取关键字
    42. //在输入目录下获取所有包含关键字的文件路径
    43. ArrayList<String> list = FileUtils.listFileString(file, key);
    44. for (Object object : list) {
    45. System.out.println(object); //将路径打印到控制台
    46. }
    47. }
    48. //***********2.指定后缀名检索文件***********
    49. private static void searchBusuffix() {
    50. Scanner sc = new Scanner(System.in);
    51. System.out.println("请输入要检索的目录位置:");
    52. String path = sc.next(); //从控制台获取路径
    53. File file = new File(path);
    54. if (!file.exists() || !file.isDirectory()) {
    55. System.out.println(path + "(不是有效目录)");
    56. return;
    57. }
    58. System.out.println("请输入搜索后缀");
    59. String suffix = sc.next();
    60. String[] suffixArray = suffix.split(","); //获取后缀字符串
    61. //在输入目录下获取所有指定后缀名的文件路径
    62. ArrayList<String> list = FileUtils.listFiles(file,suffixArray);
    63. for (Object object : list) {
    64. System.out.println(object); //将路径打印到控制台
    65. }
    66. }
    67. //***********3.复制文件/目录***********
    68. private static void copyDirectory() throws Exception {
    69. Scanner sc = new Scanner(System.in);
    70. System.out.println("请输入源目录:");
    71. String srcDirectory = sc.next(); //从控制台获取源路径
    72. File srcfile = new File(srcDirectory);
    73. if (!srcfile.exists() || !srcfile.isDirectory()) {
    74. System.out.println("无效目录!");
    75. return;
    76. }
    77. System.out.println("请输入目标位置:");
    78. String desDirectory = sc.next(); //从控制台获得目标路径
    79. File desFile = new File(desDirectory);
    80. if (!desFile.exists() || !desFile.isDirectory()) {
    81. System.out.println("无效位置!");
    82. return;
    83. }
    84. //将源路径中的内容复制到目标路径下
    85. FileUtils.copyScrPathToDestPath(srcfile, desFile);
    86. System.out.println("复制成功");
    87. }
    88. //***********4.退出***********
    89. private static void exit() {
    90. System.out.println("您已退出系统,谢谢使用!");
    91. System.exit(0);
    92. }
    93. }

    2、定义 FileUtils 类,具体如下所示。

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.FilenameFilter;
    import java.util.ArrayList;
    
    import javax.swing.filechooser.FileNameExtensionFilter;
    
    public class FileUtils {
        /**
         * 指定关键字检索文件
         * @param file    File 对象
         * @param key    关键字
         * @return    包含关键字的文件路径
         */
        public static ArrayList<String> listFileString(File file, final String key){
            FilenameFilter filter = new FilenameFilter() {
    
                @Override
                //如果文件名包含关键字返回 true,否则返回 false
                public boolean accept(File dir, String name) {
                    // TODO Auto-generated method stub
                    File currFile = new File(dir, name);
                    if (currFile.isFile() && name.contains(key)) {
                        return true;
                    }
                    return false;
                }
            };
            //递归方式获取规定的路径
            ArrayList<String> arrayList = fileDir(file, filter);
            return arrayList;
        }
        /**
         * 指定后缀检索文件
         * @param file    File 对象
         * @param suffixArrayS    后缀名数组
         * @return    指定后缀名的文件路径
         */
        public static ArrayList<String> listFiles(File file, final String[] suffixArrayS){
            FilenameFilter filter = new FilenameFilter() {
    
                @Override
                public boolean accept(File dir, String name) {
                    // TODO Auto-generated method stub
                    File currFile = new File(dir, name);
                    if (currFile.isFile()) {
                        for (String suffix : suffixArrayS) {
                            if (name.endsWith("." + suffix)) {
                                return true;
                            }
                        }
                    }
                    return false;
                }
            };
            //递归方式获取规定的路径
            ArrayList<String> arrayList = fileDir(file, filter);
            return arrayList;
        }
        /**
         * 递归方式获取规定的路径
         * @param dir    File 对象
         * @param filter    过滤器
         * @return    过滤器过滤后的文件路径
         */
        public static ArrayList<String> fileDir(File dir, FilenameFilter filter){
            ArrayList<String> arrayList = new ArrayList<String>();
            File[] lists = dir.listFiles(filter);    //获得过滤后的所有文件数组
            for (File list : lists) {
                //将文件的绝对路径放到集合中
                arrayList.add(list.getAbsolutePath());
            }
            //获得当前目录下所有文件的数组
            File[] files = dir.listFiles();
            for (File file : files) {    //遍历所有的子目录和文件
                if (file.isDirectory()) {
                    //如果是目录,递归调用 fileDir()
                    ArrayList<String> every = fileDir(file, filter);
                    arrayList.addAll(every);    //将文件夹下的文件路径添加到集合中
                }
            }//此时的集合中有当前目录下的文件路径,和当前目录的子目录下的文件路径
            return arrayList;
        }
        /**
         * 复制目录/文件
         * @param srcDir    源目录
         * @param desDir    目标目录
         * @throws Exception
         */
        public static void copyScrPathToDestPath(File srcDir, File desDir) throws Exception{
            File[] files = srcDir.listFiles();    //子文件目录
            for (int i = 0; i < files.length; i++) {
                File copiedFile = new File(desDir, files[i].getName());
                if (files[i].isDirectory()) {    //如果是目录
                    if (!copiedFile.mkdir()) {
                        System.out.println("无法新建此文件夹:“" + copiedFile + "” 因为目标目录下存在该同名文件夹");
                        return;
                    }
                    copyScrPathToDestPath(files[i], copiedFile);
                }else {
                    FileInputStream input = new FileInputStream(files[i]);
                    FileOutputStream output = new FileOutputStream(copiedFile);
                    byte[] buffer = new byte[1024];
                    int n = 0;
                    while ((n = input.read(buffer)) != -1) {
                        output.write(buffer, 0, n);
                    }
                    input.close();
                    output.close();
                }
            }
        }
    }