转载请注明源出处:http://www.cnblogs.com/lighten/p/6992043.html

1.前言

  在讲解Java的文件流之前,先来认识一下Java的文件系统的实现。值得一提的是,Java8与Java7相比,对这一块做了一些改动,接下来会进行对比介绍,但主要还是以Java8为主。

1.1 Java7与Java8不同之处概览

  首先,Java8多了一个DefaultFileSystem,但少了一个Win32FileSystem类,其次两者的抽象父类FileSystem有些许区别。Java7的抽象父类有一个静态native方法,FileSystem getFileSystem();

而Java8没有。在File类文件我们可以看到,Java7获取电脑主机的文件系统就是通过FileSystem.getFileSystem();而Java8则是通过DefaultFileSystem.getFileSystem();

  这个WinNTFileSystem是两个版本都有的一个类,但实现不一样,由于Java7存在Win32FileSystem,其WinNTFileSystem类是继承自Win32FileSystem,Java8没有这个类,所以其是直接继承抽象父类FileSystem。从这里我们也可以看出区别了,Java7是通过native方法来选择主机的文件系统实现类实例。但是Java8只有WinNTFileSystem一个实现类,没有Win32FileSystem的,因此就是直接返回一个WinNTFileSystem实例。后面将比较WinNTFileSystem在两个版本的不同之处。

2.WinNTFileSystem

  FileSystem中定义了许多的抽象方法,具体如下:

  

  涉及到文件系统的查询,添加删除都是native方法,具体如下:

private native String getDriveDirectory(int drive);    //获取磁盘目录,A~Z盘符
private native String canonicalize0(String path)
throws IOException; // 规范化文件路径
private native String canonicalizeWithPrefix0(String canonicalPrefix,
String pathWithCanonicalPrefix)
throws IOException; // 这个也是规范化,不过其假定之前的路径都是规范的,只需要规范路径最后一个元素 // 一些文件的操作,文件信息的读取,删除创建目录及文件权限等等
public native int getBooleanAttributes(File f);
public native boolean checkAccess(File f, int access);
public native long getLastModifiedTime(File f);
public native long getLength(File f);
public native boolean setPermission(File f, int access, boolean enable,
boolean owneronly);
public native boolean createFileExclusively(String path)
throws IOException;
public native String[] list(File f);
public native boolean createDirectory(File f);
public native boolean setLastModifiedTime(File f, long time);
public native boolean setReadOnly(File f);
private native boolean delete0(File f);
private native boolean rename0(File f1, File f2);
private static native int listRoots0();
private native long getSpace0(File f, int t);
private static native void initIDs();

  Java7与Java8针对于文件的一些操作方法,在WinNTFileSystem大致相同,不过Java7是将其实现在Win32FileSystem类中。虽说是大致相同,但是还是有些许差别。Win32FileSystem获取磁盘使用大小如下:

  两个版本的WinNTFileSystem的实现却是一样的。

  这里为什么不需要兼容Win32就不清楚了,或许是在使用时判断过了,或许是native方法getSpace0的实现方法不同了。而除了这个方法,两者的这个WinNTFileSystem都实现都是一样的,Java7的Win32FileSystem就是一个getSpace与WinNTFileSystem,这也难怪移除了这个类,只使用WinNTFileSystem这个类了。

  由于大部分方法都是些native方法,调用这些方法的方法实现也比较简单,这里就不进行说明了,直接看源码就很明白了。这里简单介绍一下文件路径的处理过程。

  1.public String canonicalize(String path);

    (1)判断path长度:

      长度为两位,格式是字母:,则返回大写字母:,比如C:

      长度为三位,格式是字母:\\,则返回大写字母:\\,如C:\\

    (2)判断设置是否需要缓存路径:

      不需要,调用native方法canonicalize0

      需要,获取缓存cache,存在就直接返回。不存在:

      (a)如果使用缓存的路径前缀,通过parentOrNull获取文件的父路径,没有则为null。如果父路径不为空,取缓存prefixCache,缓存为空,就调用canonicalizeWithPrefix,注意这里放入的缓存是cache,这个结果就是我们需要的整个路径格式化结果。

      (b)如果结果还是null,就使用navtive方法的canonicalize0获取格式化路径。放入cache缓存。注意,如果需要缓存前缀,并且a步骤解析的父路径不为空,就重新通过格式化后的路径获取父文件,存在且格式化后的路径也是一个文件存在且不是目录,就将结果存入prefixCache。

  这个解析过程看过去很麻烦,为什么不直接调用canonicalize0方法。主要是通过使用缓存,可以改进启动的性能。值得注意的是,a步骤和b步骤放入cache中的键值写法是不一样的,但是结果是一致的,cache处理的是相同path的格式化路径,键值就是传入的path,prefixCache处理的是父目录目录的格式化路径,取出来的是父目录的格式化路径,确保与native算法canonicalize_md.c中的结果一致,进行了相应的转换处理,所以源码看过去有些繁琐。

3.File

  File类有四种构造方法:

  不管是哪种方式,最终都是要初始化两个参数:

  下面这些文件方式,都是使用了FileSystem的与路径处理相关的方法:

  而剩下的所有方法,都与FileSystem的native方法相关了,没有太多介绍的必要。唯一有点意思的就是deleteOnExit()方法,其实现与DeleteOnExitHook类相关,这个类最后会介绍。

4.其它相关类

4.1 ExpiringCache

  第2节讲到过获取路径的标准字符串时使用到了缓存,这个缓存就是ExpiringCache类,这是一个带时效的缓存,实现关键就在于初始化的时候需要给一个超时时间

  其保存的不只是键值,值是一个Entry,有额外的保存时间字段

  在保存的时候会加上保存时间戳,获取的时候会比较一下当前时间是否超时。超时就清除返回null,否则就返回所需要的值。

4.2DeleteOnExitHook

  File类的deleteOnExit()方法就是使用了这个类。实际上开源框架dubbo的停机也使用了其中的机制。Java目前在JVM关闭的时候提供了一个钩子(hook),这个允许你在JVM关闭的时候执行一些代码,这个类就是在关闭的时候执行删除需要删除的文件。一般是通过Runtime.getRuntime().addShutdownHook(new Thread())进行的。DeleteOnExitHook是使用了一个sun.misc.SharedSecrets类来完成的,原理应该一样的。hook在以下情况会生效:

  1.程序运行完成退出

  2.使用System.exit()方法退出

  3.终端运行时使用ctrl+c中止程序

  4.系统关闭

  5.OutOfMemory造成宕机

  6.kill pid命令杀死进程(kill -9 pid不行)

Java之IO(五)文件系统的更多相关文章

  1. Java之IO(零)总结

    转载请注明原出处:http://www.cnblogs.com/lighten/p/7274378.html 1.前言 本章是对之前所讲述的整个Java的IO包的一个总结,抽出个人认为比较重要的知识点 ...

  2. Java的IO文档

    1.     File类 1.1. File类说明 存储在变量,数组和对象中的数据是暂时的,当程序终止时他们就会丢失.为了能够永 久的保存程序中创建的数据,需要将他们存储到硬盘或光盘的文件中.这些文件 ...

  3. Java进阶(五)Java I/O模型从BIO到NIO和Reactor模式

    原创文章,同步发自作者个人博客,http://www.jasongj.com/java/nio_reactor/ Java I/O模型 同步 vs. 异步 同步I/O 每个请求必须逐个地被处理,一个请 ...

  4. Java实验报告五:Java网络编程及安全

    Java实验报告五:Java网络编程及安全                                                                               ...

  5. Java基础——IO流

    今天刚刚看完java的io流操作,把主要的脉络看了一遍,不能保证以后使用时都能得心应手,但是最起码用到时知道有这么一个功能可以实现,下面对学习进行一下简单的总结: IO流主要用于硬板.内存.键盘等处理 ...

  6. JAVA的IO学习

    IO 有具体的分类: 有具体的分类:1:根据处理的数类型不同:字节流和字符流.2:根据流向不同:输入流和输出流. =============(补充字节跟字符概念区分)================= ...

  7. 使用Java API操作HDFS文件系统

    使用Junit封装HFDS import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.*; import org ...

  8. Java多线程(五)线程的生命周期

    点我跳过黑哥的卑鄙广告行为,进入正文. Java多线程系列更新中~ 正式篇: Java多线程(一) 什么是线程 Java多线程(二)关于多线程的CPU密集型和IO密集型这件事 Java多线程(三)如何 ...

  9. Java API实现Hadoop文件系统增删改查

    Java API实现Hadoop文件系统增删改查 Hadoop文件系统可以通过shell命令hadoop fs -xx进行操作,同时也提供了Java编程接口 maven配置 <project x ...

随机推荐

  1. gorename: easy refactoring tool for Golang[转]

    To inaugurate this attempt of blog, I’ll talk about gorename a small but incredibly useful tool I ju ...

  2. 下拉菜单  - - css

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  3. Windows / Windows Phone 8.1 预留应用名称及应用上传

    最近比较懒好久没有来这里跟大家聊了,WP 8.1 的 preview 发布已经有一阵子了,并且商店支持 8.1 应用也有一段时间了.我就把这篇 8.1 的应用商店预留提交作为 8.1 的一个开始吧. ...

  4. Argument list too long error for rm, cp, mv commands

    Another option is to use find's -delete flag: find . -name "*.pdf" -delete

  5. 仿建设银行APP首页效果

    仿建设银行APP首页效果 下载地址: http://pan.baidu.com/s/1eRMYEzC 下载后需要解压,解压密码联系:390980233  收费88元 HTML+JS实现,下载即可试用. ...

  6. 设计模式之外观模式(Facade Pattern)

    一.什么是外观模式? 简单的说,外观模式是用来简化接口的. 通常,我们觉得一个子系统不好用,可能是因为它提供的外部接口太接近低层组件,让我们用起来感到很麻烦. 因为我们不需要知道内部细节,我们只想要一 ...

  7. 【WPF】UserControl 的 Load事件

    经过查看MSDN,总结下 UserControl 的 Load 事件: Q1:Load事件什么时候发生? 在控件第一次变为可见之前发生. Load事件发生在创建 UserControl 时,因此有些情 ...

  8. 给IDistributedCache新增了扩展方法GetOrCreate、GetOrCreateAsync

    public static class DistributedCacheExtensions { public static TItem GetOrCreate<TItem>(this I ...

  9. ! [rejected] master -> master (non-fast-forward)

    当向GitHub远程仓库提交请求时,常会出现  ! [rejected]  master -> master (non-fast-forward) 错误. 出现这种错误通常是由于远程仓库的文件版 ...

  10. Null类型的DateTime怎么用在TimeSpan上!

    太TM简单了.. DateTime ts1 = Convert.ToDateTime(workinfo.WorkTime.ToString()); DateTime ts2 = Convert.ToD ...