重走java学习之路----IO框架(一)

本文探讨了Java中IO的基本概念及其与计算机组件的关系,并详细介绍了File类的主要用途和使用方法,包括路径处理、文件属性操作等。

问题引出:
  学习java将近两年,总感觉自己java的基础不是太牢固,打算这学期把java基础给复习一下,同时结合源码(JDK1.7)来学习一下,看不懂硬着头皮也要看(其实楼主的英语很垃圾,翻译不对,还请大家批评指正,多多见谅)。看源码,我主要想借鉴一下“大家”写代码的风范,一直认为自己的代码不上台面,写出来太丢人。唉,没办法,继续努力吧!!!


IO介绍:
  要谈IO就要从计算机的组成部分说起,根据冯.诺依曼计算机的组成,将计算机分为运算器、控制器、存储器、输入设备、输出设备,我们通常将输入设备(Input)和输出设备(Output)简写为I/O(或IO)。在java中关于IO的解释,本人更倾向于将其看作是一种计算机内部与计算机外部交换信息的手段,并且针对这种信息交换的方式,提出了“流”的概念,这个概念在生活中其实也很常见,水流、电流等。
  “对语言设计人员来说,创建好的输入/输出系统是一项特别困难的任务。”这是java编程思想里的一句话,为什么呢?IO的种类有文件、控制台、网络三种,同时通信的方式又有顺序、随机、按字节、按字符、二进制、按行等,需要把各个地方都考虑周全,的确不是一件易事。


常用介绍:
  File类:文件和目录路径名的抽象表示形式。File类主要用来操作文件的属性,例如:文件大小、文件类型、文件属性、修改/创建时间等。但是,不可以操作文件的内容,例如:添加或修改文件内容等操作。主要字段和方法如下:
 1)File.separator 系统分割符(跨平台,建议多使用);
 2)File(String pathname) 构造方法,传入文件/目录路径,若指定文件不存在,则重新创建文件。
 3)length() 获取文件长度
 4)delete() 删除文件/目录
 5)exists() 判断文件/目录是否已存在
 6)mkdir() 创建目录
 7)mkdirs() 创建目录,包括下属子目录
 8)getName() 获取文件/目录名称
 9)getAbsolutePath() 获得绝对路径
 10)isDirectory() 判断是否为目录
 11)isFile() 判断是否为文件
 12)listFile() 返回文件路径下的所有文件/目录
 13)listFile(FileFilter filter) 利用文件过滤器返回指定路径下的指定文件或目录
 File类源码学习
 源码一:

    /**
     * Enum type that indicates the status of a file path.
     */
    private static enum PathStatus { INVALID, CHECKED };

    /**
     * The flag indicating whether the file path is invalid.
     */
    private transient PathStatus status = null;

    /**
     * Check if the file has an invalid path. Currently, the inspection of
     * a file path is very limited, and it only covers Nul character check.
     * Returning true means the path is definitely invalid/garbage. But
     * returning false does not guarantee that the path is valid.
     *
     * @return true if the file path is invalid.
     */
    final boolean isInvalid() {
        if (status == null) {
            status = (this.path.indexOf('\u0000') < 0) ? PathStatus.CHECKED
                                                       : PathStatus.INVALID;
        }
        return status == PathStatus.INVALID;
    }

    public boolean delete() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkDelete(path);
        }
        if (isInvalid()) {
            return false;
        }
        return fs.delete(this);
    }

System.getSecurityManager();获取系统安全接口的SecurityManager对象(安全管理器对象:该对象主要是用来判断是否可以执行用户的敏感性操作),例如上图中执行的删除检查checkDelete(path)。然后再是验证文件路径是否合法(检验方法就是Unicode下的空白字符检验,‘\u0000’第一次见,在java输出显示一个“空格子”)。isInvalid()方法中的返回值有点看不太明白,仔细一看,是枚举类型的使用(假如通过验证,比较后返回false,假如验证失效,比较后返回true)。验证之后进行相应的判断,无效直接返回false,否则继续向下执行,获得文件系统对象,执行删除操作。
源码二:

    public String[] list() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkRead(path);
        }
        if (isInvalid()) {
            return null;
        }
        return fs.list(this);
    }

    public String[] list(FilenameFilter filter) {
        String names[] = list();
        if ((names == null) || (filter == null)) {
            return names;
        }
        List<String> v = new ArrayList<>();
        for (int i = 0 ; i < names.length ; i++) {
            if (filter.accept(this, names[i])) {
                v.add(names[i]);
            }
        }
        return v.toArray(new String[v.size()]);
    }

关于list()和list(FilenameFilter filter)的大致相似,注意异常终止的使用集合转换数组的方式
源码三:

public File[] listFiles() {
        String[] ss = list();
        if (ss == null) return null;
        int n = ss.length;
        File[] fs = new File[n];
        for (int i = 0; i < n; i++) {
            fs[i] = new File(ss[i], this);
        }
        return fs;
    }

通过上述的list()方法,获取指定文件夹下的文件/目录名字的字符串数组
本地的私有构造方法如下:

/**
     * Internal constructor for already-normalized pathname strings.
     * The parameter order is used to disambiguate this method from the
     * public(File, String) constructor.
     */
    private File(String child, File parent) {
        assert parent.path != null;
        assert (!parent.path.equals(""));
        this.path = fs.resolve(parent.path, child);
        this.prefixLength = parent.prefixLength;
    }

要注意断言的使用方式(虽然项目中几乎不用):

//第一种方式
assert boolean表达式;
//第二种方式
assert boolean表达式 : 详细的信息;

boolean表达式的结果为true时,则什么信息都不会显示,当boolean表达式为false时,若指定显示错误信息,则显示自定义的指定信息,若不指定则显示系统默认。
源码四:

    public File[] listFiles(FilenameFilter filter) {
        String ss[] = list();
        if (ss == null) return null;
        ArrayList<File> files = new ArrayList<>();
        for (String s : ss)
            if ((filter == null) || filter.accept(this, s))
                files.add(new File(s, this));
        return files.toArray(new File[files.size()]);
    }

文件过滤器的源码构造,注意写法思路。
OK,File类的源码先告一段落,下面介绍一下Java中IO流的使用过程及分类(注意这是重点)


IO流使用过程:
  1) 创建节点流
  2) 封装过滤流
  3) 读/写数据
  4) 关闭流


IO流分类:
  1)按照流的方向分:输入流/输出流
  2)按照流的数据单位分:字节流/字符流
  3)按照流的功能分:节点流/过滤流
  注意:
  1)“输入流”与“输出流”的方向全部是相对JAVA虚拟机(JVM)来讲的。具体见下图:
JVM图描述“流”的方向
  2)字节流和字符流的关系。(简体中文的window系统默认是GBK编码)在GBK编码下,两个字节代表一个字符,一个汉字要用两个字节来表示,所以一个汉字可以用一个字符来表示(这也是字符流出现的原因,为了方便读取文本文件)。另外,正是由于以上的关系,任何数据都可以使用字节流来读取,只是当读取中文文本的时候可能会出现“乱码”。平常使用次数最多的就是字符流,但是字节流是基础,不可忽视
  
  3)节点流和过滤流的关系。由最上面的图可以看出,流的传输全部发生在节点与节点之间,这就是节点流。但有些时候,仅仅使用节点流并不能完全满足我们的需求,需要将节点流的功能进一步放大,我们称这些流为过滤流(其实本人更愿意叫“增强流”或“辅助流”)。


第一节大致就介绍到这里,下一节继续介绍关于各种“流”的源码。其实我的内心是很开(tong)心(ku)的。对了,今天挖个坑,枚举的使用需要好好研究一下,以后找个时间,专门写一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值