zoukankan      html  css  js  c++  java
  • 文件流-1

    对于程序语言的设计者来说,创建一个好的输入输出系统是一个艰巨的任务

    File类

    File类这个名字有一定的误导性,我们可能会认为它指代的是文件,然而却并非如此,它既能表明一个文件特定的名称,又能代表一个目录下一组文件的名称,如果他指的是文件集,我们就可以对此集合调用list方法,会返回一个字符数组,也及时目录列表


          假设我们想查看一个目录列表,可以用两种方法来使用File对象。如果我们调用不带参数的list0方法,便可以获得此File对象包含的全部列表。然而,如果我们想获得一个受限列表,例如,想得到所有扩展名为java的文件,那么我们就要用到“目录过滤器”,这个类会告诉我们怎样显示符合条件的File对象。

          下面是一一个示例,注意,通过使用java.utils.Arrays.sort和String.CASE INSENSITIVE.ORDERComparator,可以很容易地对结果进行排序(按字母顺序)。


    class DirFilter implements FilenameFilter {
        private Pattern p;
    
        public DirFilter(String regex) {
            p = Pattern.compile(regex);
        }
    
        @Override
        public boolean accept(File dir, String name) {
            // TODO Auto-generated method stub
            return p.matcher(name).matches();
        }
    
    }
    
    class DirFilter2 {
        // 参数是final是必须的,这是匿名内部类必须的,这样才能使用来自该范围之外的对象
        public static FilenameFilter filter(final String regex) {
            return new FilenameFilter() {
    
                private Pattern p = Pattern.compile(regex);
    
                @Override
                public boolean accept(File dir, String name) {
                    // TODO Auto-generated method stub
                    return p.matcher(name).matches();
                }
    
            };
        }
    
    }
    
    public class file {
        public static void main(final String[] args) {
            File path = new File(".");
            String[] list;
            if (args.length == 0)
                list = path.list();
            else {
                System.out.println("false");
                // 第一
                list=path.list(new DirFilter(args[0]));//回调,,会调用accept方法
                // 第二
                // list=path.list(DirFilter2.filter(args[0]));
                // 第三,添加final,优点是将解决特定问题的代码隔离,聚拢于一点,但是却不易阅读,要谨慎使用
                /*list = path.list(new FilenameFilter() {
    
                    private Pattern p = Pattern.compile(args[0]);
    
                    @Override
                    public boolean accept(File dir, String name) {
                        // TODO Auto-generated method stub
                        return p.matcher(name).matches();
                    }
                });*/
            }
            Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
            for (String item : list) {
                System.out.println(item);
            }
        }
    
        /**
         * 得到指定路径下的文件列表
         * 
         * @param path
         */
        public void getFileList(String path) {
            File f = new File(path);
            for (String name : f.list()) {
                System.out.println(name);
            }
        }
    
        /**
         * 得到当前的文件目录列表
         */
        @Test
        public void getFilelist() {
            File path = new File(".");
            for (File f : path.listFiles()) {
                if (f.isDirectory()) {
                    System.out.println("文件夹:" + f.getName());
                } else {
                    System.out.println("记事本:" + f.getName());
    
                }
            }
        }
    }


          DirFiter这个类存在的唯一原因就是将accept方法。创建这个类的目的在于把accept0方法提供给listO使用,使list(可以回调accept,进而以决定哪些文件包含在列表中。因此,这种结构也常常称为回调。更具体地说,这是-一个策略模式的例子,因为list(实现了基本的功能,而且按照FilenameFilter的形式提供了这个策略,以便完善listO在提供服务时所需的算法。因为list(接受FilenameFilter对象作为参数,这意味着我们可以传递实现了FilenameFilter接口的任何类的对象,用以选择(甚至在运行时) list方 法的行为方式。策略的目的就是提供了代码行为的灵活性。

          accept方法必须接受-一个代表某个特定文件所在目录的File对象,以及包含了那个文件名的一个String。记住一点: list方法会为此目录对象下的每个文件名调用accept,来判断该文件是否包含在内;判断结果由accept返回的布尔值表示。

          accept会使用一个 正则表达式的matcher对象,来查看此正则表达式regex是否匹配这个文件的名字。通过使用accept, list方法会返回一个数组。

     DirFilter2用了匿名内部类

    这个例子很适合用一个匿名内部类进行改写。首先创建一个filter方法,它会返回一个指向FilenameFilter的引用注意,传向flter的参数必须是final的。这在匿名内部类中是必需的,这样它才能够使用来自该类范围之外的对象。这个设计有所改进,因为现在FilenameFilter类 紧密地和DirList2绑定在一起。然而,我们可以进一步修改该方法,定义一个作为list参数的匿名内部类;这样一来程序会变 得更小:比如在上的代码中main方法标注的第三部分中直接使用了匿名内部类,没有对别的对象产生依赖
    既然匿名内部类直接使用args[0],那么传递给main方法的参数现在就是final的。
    这个例子展示了匿名内部类怎样通过创建特定的、一次性的类来解决问题。此方法的一个优点就是将解决特定问题的代码隔离、聚拢于-一点。而另一方面,这种方法却不易阅读,因此要谨慎使用。

          程序设计中一项常见的任务就是在文件集上执行操作,这些文件要么在本地目录中,要么遍布于整个目录树中。如果有一种工具能够为你产生这个文件集,那么它会非常有用。下面的实用工具类就可以通过使用local0方法产生由本地目录中的文件构成的File对象数组,或者通过使用walk0方法产生给定目录下的由整个目录树中所有文件构成的List<File> (File对象 比文件名更有用,因为File对象包含更多的信息)。这些文件是基于你提供的正则表达式而被选中的:


    import java.io.File;
    import java.io.FilenameFilter;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    import java.util.regex.Pattern;
    
    public final class Directory {
        public static File[] local(File f, final String regex) {
            return f.listFiles(new FilenameFilter() {
                private Pattern p = Pattern.compile(regex);
    
                @Override
                public boolean accept(File dir, String name) {
                    // TODO Auto-generated method stub
                    return p.matcher(name).matches();
                }
            });
        }
    
        public static File[] local(String path, final String regex) {
            return local(new File(path), regex);
        }
    
        public static class TreeInfo implements Iterable<File> {
            public List<File> files = new ArrayList<File>();
            public List<File> dirs = new ArrayList<File>();
    
            @Override
            public Iterator<File> iterator() {
                // TODO Auto-generated method stub
                return files.iterator();
            }
    
            void addAll(TreeInfo other) {
                files.addAll(other.files);
                files.addAll(other.dirs);
            }
    
            public String toString() {
                return "dir: " + PPrint.pFormat(dirs) + "
    
    " + "file: " + PPrint.pFormat(files);
            }
        }
    
        public static TreeInfo walk(File start, String regex) {
            return recurseDirs(start, regex);
        }
    
        public static TreeInfo walk(String start, String regex) {
            return recurseDirs(new File(start), regex);
        }
    
        public static TreeInfo walk(File start) {
            return recurseDirs(start, ".*");
        }
    
        public static TreeInfo walk(String start) {
            return recurseDirs(new File(start), ".*");
        }
    
        static TreeInfo recurseDirs(File f, String regex) {
            TreeInfo t = new TreeInfo();
            for (File item : f.listFiles()) {
                if (item.isDirectory()) {
                    t.dirs.add(item);
                    t.addAll(recurseDirs(item, regex));
                } else {
                    if (item.getName().matches(regex))
                        t.files.add(item);
                }
            }
            return t;
        }
    
        public static void main(String[] args) {
            if (args.length == 0) {
                System.out.println(walk("E:\学道\HTML\Commons"));
            } else {
                for (String arg : args) {
                    System.out.println(walk(arg));
                }
            }
        }
    }


          local0方法使用被称为listFileO的File.list(的变体来产生File数组。可以看到,它还使用了FilenameFilter。如果需要List而不是数组,你可以使用Arrays.asListO自己对结果进行转换。

          walk方法将开始目录的名字转换为File对象,然后调用recurseDirs,该方法将递归地遍历目录,并在每次递归中都收集更多的信息。为了区分普通文件和目录,返回值实际上是一个对象“元组”一个List持有所有普通文件, 另一个持有目录。这里,所有的域都被有意识地设置成了public,因为TreeInfo的使命只是将对象收集起来一-如果你只是返回List, 那么就不需要将其设置为private,因为你只是返回一个对象对,不需要将它们设置为private。注意,TreeInfo实现了Iterable<File>,它将产生文件,使你拥有在文件列表上的“ 默认迭代”,而你可以通过声明“.dirs” 来指定目录。

          TreeInfo.toString方法使用了一个“灵巧打印机”类,以使输出更容易浏览。容器默认的toString方法会在单个行中打印容器中的所有元素,对于大型集合来说,这会变得难以阅读,因此你可能希望使用可替换的格式化机制。下面是一个可以添加新行并缩排所有元素的工具:

    import java.io.File;
    import java.util.Arrays;
    import java.util.Collection;
    import java.util.List;
    /**
     * 加上【】
     * @author 11153
     *
     */
    public class PPrint {
        public static String pFormat(Collection<?> con) {
            if(con.size()==0) return "[]";
            StringBuilder result=new StringBuilder("[");
            for(Object e:con) {
                if(con.size()!=1) result.append("
      ");
                result.append(e);
            }
            if(con.size()!=1) {
                result.append("
    ");
            }
            result.append("]");
            return result.toString();
        }
        public static void pprint(Object[] o) {
            System.out.println(pFormat(Arrays.asList(o)));
        }
        public static void pprint(List<File> dirs) {
            System.out.println(pFormat(dirs));
        }
        public static void main(String[] args) {
            PPrint.pprint(Directory.walk("E:\学道\HTML\编程全解").dirs);
            PPrint.pprint(Directory.walk("E:\学道\HTML\编程全解").files);
        }
    }


          pformat方法可以从Collection中产生格式化的String,而pprint0方 法使用pformat0来执行其任务。注意,没有任何元素和只有一个元素这两种特例进行了不同的处理。上面还有一 一个用于数组的pprint版本。
    我们可以更进一步,创建一个工具,让他可以在目录中穿行,并且根据Strategy对象那个来处理哲学目录中的文件,这是策略设计模式的另一实例


    package File;
    
    import java.io.File;
    import java.io.IOException;
    
    public class ProcessFiles {
    
        public interface Strategy {
            void process(File f);
        }
        private String ext;
        private Strategy s;
        public ProcessFiles(Strategy s,String ext){
            this.s=s;
            this.ext=ext;
        }
    
        public void start(String[] args) {
            try {
                if (args.length == 0) {
                    processDirectoryTree(new File("."));
                } else {
                    for (String arg : args) {
                        File f = new File(arg);
                        if (f.isDirectory())
                            processDirectoryTree(f);
                        else {
                            if (!arg.endsWith("." + ext))
                                arg += "." + ext;
                            s.process(new File(arg).getCanonicalFile());
                        }
                    }
                }
            } catch (IOException e) {
    
            }
        }
    
        public void processDirectoryTree(File root) throws IOException {
            for (File f : Directory.walk(root.getAbsolutePath(), ".*\." + ext))
                s.process(f.getCanonicalFile());
        }
    
        public static void main(String[] args) {
            new ProcessFiles(new ProcessFiles.Strategy() {
                public void process(File f) {
                    System.out.println(f);
                }
            },"java").start(args);;
        }
    }


          Strategy接口内嵌在ProcessFiles中,使得如果你希望实现它,就必须实现ProcessFiles.Strategy,它为读者提供了更多的上下文信息。ProcessFiles执行 了查找具有特定扩展名(传递给构造器的ext参数)的文件所需的全部工作,并且当它找到匹配的文件时,将直接把文件传递给Strategy对象(也是传递给构造器的参数)。

          如果你没有提供任何参数,那么ProcessFiles就假设你希望遍历当前目录下的所有目录。你也可以指定特定的文件,带不带扩展名都可以(如果必需的话,它会添加上扩展名),或者指定一个或多个目录。

          在main方法中,你看到了如何使用这个工具的基本示例,它可以根据你提供的命令行来打印所有的Java源代码文件的名字。


     




     
     
  • 相关阅读:
    SNMP++
    临界区,互斥量,信号量,事件的区别
    2015 年最棒的 5 个 HTML5 框架(转)
    java.lang.OutOfMemoryError: PermGen space及其解决方法
    java.net.SocketException: Unrecognized Windows Sockets error: 0: JVM_Bind
    eclipse安装tomcat插件
    (转)Activity的跳转与传值
    Android SDK下载和更新失败的解决方法
    Android客户端WebView控件与Javascript交互
    SCI期刊
  • 原文地址:https://www.cnblogs.com/QianYue111/p/10492330.html
Copyright © 2011-2022 走看看