`
seraphim.leo
  • 浏览: 24105 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java I/O 系统 (一)

 
阅读更多

File类

 

 

一、目录列表器

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

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

 

 

public class DirList{
	public static void main(String [] args){
		File path = new File(".");
		String [] list ;
		String [] paras = {"src"};
		if(paras.length == 0)
			list = path.list();
		else
			list = path.list(new DirFilter(paras[0]));
		
		Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
		for(String dirItem : list)
			System.out.println(dirItem);
	}
}


class DirFilter implements FilenameFilter{
	private Pattern pattern ;
	public DirFilter(String regex){
		pattern = Pattern.compile(regex);
	}
	
	public boolean accept(File dir , String name){
		return pattern.matcher(name).matches();
	}
}

 

 

这里,DirFilter类“实现”了FilenameFilter接口。请注意FilenameFilter接口是多么的简单:

 

 

public interface FilenameFilter {
    /**
     * Tests if a specified file should be included in a file list.
     *
     * @param   dir    the directory in which the file was found.
     * @param   name   the name of the file.
     * @return  <code>true</code> if and only if the name should be
     * included in the file list; <code>false</code> otherwise.
     */
    boolean accept(File dir, String name);
}

 

 

创建DirFilter的目的在于把accept()方法提供给list()使用,使list()可以回调accept(),进而决定哪些文件包含在列表中。以下是File.list()及File.list(FilenameFilter filter)的实现。

 

 

/**
     * Returns an array of strings naming the files and directories in the
     * directory denoted by this abstract pathname.
     *
     * <p> If this abstract pathname does not denote a directory, then this
     * method returns <code>null</code>.  Otherwise an array of strings is
     * returned, one for each file or directory in the directory.  Names
     * denoting the directory itself and the directory's parent directory are
     * not included in the result.  Each string is a file name rather than a
     * complete path.
     *
     * <p> There is no guarantee that the name strings in the resulting array
     * will appear in any specific order; they are not, in particular,
     * guaranteed to appear in alphabetical order.
     *
     * @return  An array of strings naming the files and directories in the
     *          directory denoted by this abstract pathname.  The array will be
     *          empty if the directory is empty.  Returns <code>null</code> if
     *          this abstract pathname does not denote a directory, or if an
     *          I/O error occurs.
     *
     * @throws  SecurityException
     *          If a security manager exists and its <code>{@link
     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
     *          method denies read access to the directory
     */
    public String[] list() {
	SecurityManager security = System.getSecurityManager();
	if (security != null) {
	    security.checkRead(path);
	}
	return fs.list(this);
    }

    /**
     * Returns an array of strings naming the files and directories in the
     * directory denoted by this abstract pathname that satisfy the specified
     * filter.  The behavior of this method is the same as that of the
     * <code>{@link #list()}</code> method, except that the strings in the
     * returned array must satisfy the filter.  If the given
     * <code>filter</code> is <code>null</code> then all names are accepted.
     * Otherwise, a name satisfies the filter if and only if the value
     * <code>true</code> results when the <code>{@link
     * FilenameFilter#accept}</code> method of the filter is invoked on this
     * abstract pathname and the name of a file or directory in the directory
     * that it denotes.
     *
     * @param  filter  A filename filter
     *
     * @return  An array of strings naming the files and directories in the
     *          directory denoted by this abstract pathname that were accepted
     *          by the given <code>filter</code>.  The array will be empty if
     *          the directory is empty or if no names were accepted by the
     *          filter.  Returns <code>null</code> if this abstract pathname
     *          does not denote a directory, or if an I/O error occurs.
     *
     * @throws  SecurityException
     *          If a security manager exists and its <code>{@link
     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
     *          method denies read access to the directory
     */
    public String[] list(FilenameFilter filter) {
	String names[] = list();
	if ((names == null) || (filter == null)) {
	    return names;
	}
	ArrayList v = new ArrayList();
	for (int i = 0 ; i < names.length ; i++) {
	    if (filter.accept(this, names[i])) {
		v.add(names[i]);
	    }
	}
	return (String[])(v.toArray(new String[v.size()]));
    }

 

因此,这种结构也常常称为回调更具体的说,这是一个策略模式的例子,因为list()实现了基本的功能,而且按照FilenameFilter的形式提供了这个策略,以便完善list()在提供服务时所需的算法。因为list()接受FilenameFilter对象作为参数,这意味着我们可以传递实现了FilenameFilter接口的任何类的对象,用以选择list() 方法的行为方式。策略的目的就是提供了代码行为的灵活性

 

 

匿名内部类

这个例子很合适用一个匿名内部类进行改写,首先创建一个filter()方法,他会返回一个指向FilenameFilter的引用:

 

 

public class DirList {
	public static FilenameFilter filter(final String regex) {
		return new FilenameFilter() {
			private Pattern pattern = Pattern.compile(regex);

			public boolean accept(File dir, String name) {
				return pattern.matcher(name).matches();
			}
		};
	}

	public static void main(String[] args) {
		File path = new File(".");
		String[] list;
		if (args.length == 0) {
			list = path.list();
		} else {
			list = path.list(filter(args[0]));
		}

		Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
		for (String dirItem : list) {
			System.out.println(dirItem);
		}
	}
}

 

 

这个设计有所改进,因为现在FilenameFilter类紧密的和DirList绑定在一起。然而,我们可以进一步修改方法,定义一个作为list()参数的匿名内部类,这样一来程序会变的更小:

 

 

public class DirList {

	public static void main(final String[] args) {
		File path = new File(".");
		String[] list;
		if (args.length == 0) {
			list = path.list();
		} else {
			list = path.list(new FilenameFilter() {
				private Pattern pattern = Pattern.compile(args[0]);

				@Override
				public boolean accept(File dir, String name) {
					// TODO Auto-generated method stub
					return pattern.matcher(name).matches();
				}

			});
		}

		Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
		for (String dirItem : list) {
			System.out.println(dirItem);
		}
	}
}

 

 

 

这个例子展示了匿名内部类怎样通过创建特定的、一次性的类来解决问题,此方法的一个优点就是将解决特定问题的代码隔离、聚拢与一点。而另一方面,这种方法却不易阅读,因此要谨慎使用。

 

 

 

 

 

二、目录实用工具

程序设计中一项常见的任务就是在文件集上执行操作,这些文件要么在本地目录中,要么遍布于整个目录树中。如果有一种工具能够为你产生这个文件及,那么他会非常有用。下面的使用工具类就可以通过使用local()方法产生由本地目录中的文件构成的File对象数组,或者通过使用walk()方法产生给定目录下的由整个目录树中所有文件构成的List<File>

 

三、目录的检查及创建

File类不仅仅只代表存在的文件或目录。也可以用File对象来创建新的目录或尚不存在的整个目录路径。我们可以查看文件的特性(如:大小,最后修改日期,读写),检查某个File对象代表的是一个文件还是一个目录,并可以删除文件。下面的示例展示了File类的一些其他方法

 

 

public class MakeDirctories {
	/**
	 * 提示出错信息
	 */
	private static void usage() {
		System.err.println("Usage:MakeDirectories path1 ...\n"
				+ "Creates each path\n"
				+ "Usage:MakeDirecotries -d path1 ...\n"
				+ "Deletes each path\n"
				+ "Usage:MekeDirectories -r path1 path2 \n"
				+ "Renames from path1 to path2");
		System.exit(1);
	}

	/**
	 * 打印文件信息
	 * @param f
	 */
	private static void fileData(File f) {
		System.out.println("Absolute path : " + f.getAbsolutePath()
				+ "\n Can read : " + f.canRead() 
				+ "\n Can write : "+ f.canWrite() 
				+ "\n getName : " + f.getName()
				+ "\n getParent : " + f.getParent() 
				+ "\n getPath : "+ f.getPath() 
				+ "\n length : " + f.length()
				+ "\n lastModified : " + f.lastModified());

		if (f.isFile()) {
			System.out.println("It's a file");
		} else if (f.isDirectory()) {
			System.out.println("It's a directory");
		}
	}

	public static void main(String[] args) {
		// 监测到未输入参数 提示错误信息
		if (args.length < 1)
			usage();

		// 输入参数-r
		if (args[0].equals("-r")) {
			// 如果参数个数不是3个 提示错误信息
			if (args.length != 3)
				usage();
			// 执行修改文件名称
			File old = new File(args[1]), rname = new File(args[2]);
			old.renameTo(rname);
			fileData(old);
			fileData(rname);
			return;
		}

		int count = 0;
		boolean del = false;
		// 输入参数 -d
		if (args[0].equals("-d")) {
			count++;
			del = true;
		}

		count--;
		while (++count < args.length) {
			File f = new File(args[count]);
			if (f.exists()) {
				System.out.println(f + " exists");
				if (del) {
					System.out.println("deleting ... " + f);
					f.delete();
				}
			} else {
				if (!del) {
					f.mkdirs();
					System.out.println("created " + f);
				}
			}
			fileData(f);
		}
	}
}
 

例子里面写了一个mkdirs()方法,我们来研究一下源码:

 

 

    public boolean mkdirs() {
	if (exists()) {
	    return false;
	}
	if (mkdir()) {
 	    return true;
 	}
        File canonFile = null;
        try {
            canonFile = getCanonicalFile();
        } catch (IOException e) {
            return false;
        }

	File parent = canonFile.getParentFile();
	return (parent != null && (parent.mkdirs() || parent.exists()) &&
		canonFile.mkdir());
    }

 

 

这是一个递归方法。关键在于return,使用当前File对象的parent对象构造文件,如果parent不为空,并且parent调用mkdirs创建成功或者parent已经存在,并且标准文件可以创建,则返回true,否则的话就继续调用mkdirs方法,直到递归到根目录下为止。

 

以下是getCanonicalFile方法的源码,这个方法返回抽象路径名的规范形式。说白了就是创建一个以规范路径名命名的File对象,他等同于new File(this.getCanonicalPath())。

 

 

    public File getCanonicalFile() throws IOException {
        String canonPath = getCanonicalPath();
	return new File(canonPath, fs.prefixLength(canonPath));
    }

 

 

这里调用了getCanonicalPath方法,这个方法返回抽象路径名的规范路径名字符串。

 

 

    public String getCanonicalPath() throws IOException {
	return fs.canonicalize(fs.resolve(this));
    }

 

 

分享到:
评论

相关推荐

    java数据流 I/O系统

    描述java的I/o系统,描述了java中文件系统的处理,数据流的处理

    Java I/O学习笔记: 磁盘操作 字节操作 字符操作 对象操作 网络操作 NIO & AIO Java I/O

    Java I/O学习笔记: 磁盘操作 字节操作 字符操作 对象操作 网络操作 NIO & AIO Java I/O Java是一种面向对象的编程语言,由Sun Microsystems于1995年推出。它是一种跨平台的语言,意味着可以在不同的操作系统上运行...

    java I/O类的使用

    简单介绍了java 的输入输出系统中类的使用,java1.0和java1.1中的类的来源去向

    Java I/O系统

    NULL 博文链接:https://xace.iteye.com/blog/703920

    基于I/O、多线程、GUI的标准考试系统v1.0(JAVA实现)

    本系统是基于JAVA开发平台,运用Socket网络编程,I/O文件流,线程,Swing图形界面等技术,实现的一套标准化考试系统。通过该系统可以完成多个科目的标准化考试工作。 该系统共分为三个模块:考生客户端,服务器端和...

    探索Java I/O 模型的演进

    什么是同步?什么是异步?阻塞和非阻塞又有什么区别?本文先从 Unix 的 I/O ...而后再引出 Java 的 I/O 模型的演进过程,并用实例说明如何选择合适的 Java I/O 模型来提高系统的并发量和可用性。,需要的朋友可以参考下

    java使用简单的I/O编写的投票系统

    java使用简单的I/O编写的投票系统

    Java I/O底层是如何工作的?

    本博文主要讨论I/O在底层是如何工作的。本文服务的读者,迫切希望了解Java I/O操作是在机器层面如何进行映射,以及应用运行时硬件都做了什么。...通常,进程执行操作系统的I/O请求包括数据从缓冲区排

    彻底明白 Java 语言中的IO系统

    彻底明白 Java 语言中的IO系统 彻底明白 Java 语言中的IO系统

    Java I/O深入学习之File和RandomAccessFile

    主要介绍了Java I/O深入学习之File和RandomAccessFile, I/O系统即输入/输出系统,对于一门程序语言来说,创建一个好的输入/输出系统并非易事。在充分理解Java I/O系统以便正确地运用之前,我们需要学习相当数量的...

    java_I/ODemo

    对程序语言的设计者来说,创建一个好的输入/输出(I/O)系统是一项艰难的任务,在整个Java.io包中最重要的就是5个类和一个接口。5个类指的是File、OutputStream、InputStream、Writer、Reader;一个接口指的是...

    使用Java实现一个简单的文件管理系统.txt

    这段代码实现了一个简单的文件管理系统,其中使用了Java的I/O类库。在类的构造方法中,首先创建了一个File对象来表示要操作的文件,如果该文件不存在则创建新文件。然后通过FileReader和BufferedReader类来读取文件...

    java nio超好资源

    NIO 的创建目的是为了让 Java 程序员可以实现高速 I/O 而无需编写自定义的本机代码。NIO 将最耗时的 I/O 操作(即填充和提取缓冲区)转移回操作系统,因而可以极大地提高速度。

    java基础知识I/O流使用详解

    编程语言的I/O类库中常常使用流这个抽象的概念,它代表任何有能力产生数据的数据源对象或时有能力接收数据的接收端对象,本文为大家介绍Java中I/O系统基础知识

    基于I/O流设计的图书馆管理系统

    这个是我基于I/O流设计的图书馆管理系统项目总结,是有篇文章的,如果实在不会整再来下载这个完整的。文章:https://blog.csdn.net/GB__LaoWang/article/details/115914058

    彻底明白 Java 语言中的IO系统 .pdf

    彻底明白 Java 语言中的IO系统 .pdf

    基于java NIO的简单聊天软件示例

    JAVA NIO有两种解释:一种叫非阻塞IO(Non-blocking I/O),另一种也叫新的IO(New I/O),其实是同一个概念。它是一种同步非阻塞的I/O模型,也是I/O多路复用的基础,已经被越来越多地应用到大型应用服务器,成为...

    彻底明白Java的IO系统

    彻底明白Java的IO系统,知道I/O内部运行机制。

    Thinking in Java 4th Edition(中文扫描版-带目录和源码)

    本书共22章,包括操作符、控制执行流程、访问权限控制、复用类、多态、接口、通过异常处理错误、字符串、泛型、数组、容器深入研究、JavaI/O系统、枚举类型、并发以及图形化用户界面等内容。这些丰富的内容,包含了...

    Java实现的小型文件管理系统

    文件批量处理用(Eclipse)Java实现,模块为了方便管理文件而设计,通过本模块可以快速地实现文件的批量复制、批量删除、批量重命名、文件分类等。内含设计文档,包括使用说明。还有打包好的可运行的jar文件。

Global site tag (gtag.js) - Google Analytics