美文网首页
Java之IO流

Java之IO流

作者: Jowney | 来源:发表于2018-05-13 00:39 被阅读7次

    一.流的属性

    书上一般说的·都是流的分类,但是我感觉说属性更合适。因为一个流只要存在,那么它就有方向,可操作的最小数据元,有自己的功能。根据这些属性我们就可以准确的定义一个流。(纯属个人理解,如有误望不吝指正)~(^ O^)~
    1)输入流、输出流(从流向划分)
    Java的输入流主要由InputStream、Reader作为基类;
    Java的输出流主要有OutputStream、Writer作为基类。
    注意他:们都是抽象类无法直接创建实例

    2)字节流、字符流(从操作的数据原划分)
    字节流主要由InputStream、OutputStream作为基类,其操作的数据单元是8位的字节;
    字符流主要有Reaer、Writer作为基类,其操作的数据单元为两个字节16位的字符。

    3)节点流、处理流(从流的功能划分)
    节点流又叫低级流,它是直接与数据源(把数据源叫做节点,如磁盘、网络)连接的流;
    处理流又叫高级流或者包装流,它将低级流进行二次包装,然后实现数据的读写。

    输入输出流体系中的常用流分类

    二.流的判断

    1)InputStream的子类实现的流一定是输入流、字节流。至于是节点流还是处理流,那就要看它的具体功能了。
    2)Reader的子类实现的流一定是输入流、字节流。至于是节点流还是处理流,那就要看它的具体功能了。
    注意:我们在研究流的时候其实主要关注它是节点流还是处理流,因为其他类型从它的实现类就可以看出来。

    三.流的概念模型

    理解流的模型对后面的学习会有很大的帮助。因为Java IO流共涉及40多个类,这些类看上去杂乱繁多,但实际非常有规则,而且彼此之间存在非常紧密的联系。Java IO流的四十多个类都是由InputStream、OutputStream、Writer、Reaer这四个基类派生出来的。
    1)输入流、节点流模型

    • 模型


      输入流模型图
    • 例子
    public static void main(String[] args) throws IOException {
    
            InputStream in = null;
            File f = new File("D:/test.txt");
    
            byte[] b = new byte[2];
    
            in = new FileInputStream(f);//从名字中能分析出那些信息?File代表它直接连接的数据源是File,InputStream指明了它的父类
            int i = 0;
            while ((i = in.read(b)) != -1) {
                String str = new String(b);
                System.out.print(str);
            }
    
    • 讲解
      对于模型的理解书中原话是:输入流使用隐式的记录指针来表示当前当前从哪个水滴开始读取,每当读取一个或多个水滴以后,记录指针会自动往后移。如果是字节流一个水滴代表一个字节,如果是字符流一个水滴代表两个字节。
      模型是人们为了方便理解而抽象出来的东西,下面我们结合例子和模型进行理解。
      在实例中我们创建了一个FileInputStrea(从名字中我们可以推测出它是一个输入、字节、节点流),它就相当与模型中的那个装满水滴的管道,每个水滴代表一个字节。也就是说FileInputStream这个管道在实例中装的是D:/test.txt这个文件的内容。我们每次读取2个字节,记录指针每次也会跟着移动,我们把管道里的内容读完。

    2)输出流、节点流模型

    • 模型
      当执行输出的时候,程序相当于依次把水滴放入到输出流的管道中,输出流同样采取隐式的记录指针来标识当前水滴的位置,每当程序向管道里放入一个或着多个水滴,记录指针自动后移。


      输出流模型图
    • 实例
      public static void main(String[] args) {
            FileOutputStream fop = null;
            File file;
            String content = "This is the text content";
          
            try {
                file = new File("newfile.txt");
                fop = new FileOutputStream(file);
             
                // if file doesnt exists, then create it
                if (!file.exists()) {
                    file.createNewFile();
                }
                // get the content in bytes
                byte[] contentInBytes = content.getBytes();
                fop.write(contentInBytes);
             
                System.out.println("Done");
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (fop!=null){
                        fop.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
    • 讲解
      在实例中创建了FileOutpStream这个空的管道,将内容输出到指定的位置。
      3)处理流模型
    • 模型


      处理流模型图
    • 讲解
      处理流(包装流)可以包装任何已存在的节点流,包装之后就可以用相同的代码来控制不同的节点流,同时也可以提升效率。

    四.节点流

    1)所有输入节点流的抽象基类InputStream、Reader

    • InputStream里面包含了如下三个方法:
      int read() 从输入流中读取单个字节,返回读取的字节数据(字节数据可直接转换成的int类型)
      int read(byte[ ] b) 从流中读取b.length个字节数据,并将其存储在字节数组b中,返回实际读取的字节数
      int read(byte[] b,int off,int len) 从流off位置开始,每次最多读取len字节的数据,并放入b字节数组,最后返回实际读取的
      void mark(int readAHeadLimit) 记录指针当前位置
      boolean markSupported() 判断此输入流是否支持及mark操作
      void reset() 将此流的记录指针重新定位到上一次mark的位置
      long skip(long n) 将记录指针向前移动n个字节
      字节数
    • Reader里面包含的三个方法:
      int read() 从输入流中读取单个字符,返回读取的字符数据(字符数据直接转换成的int类型)
      int read(char[ ] b) 从流中读取b.length个字符数据,并将其存储在字符数组b中,返回实际读取的字符数
      int read(cahr[] b,int off,int len) 从流off位置开始,每次最多读取len字符的数据,并放入b字符数组,最后返回实际读取的字符数
      void mark(int readAHeadLimit) 记录指针当前位置
      boolean markSupported() 判断此输入流是否支持及mark操作
      void reset() 将此流的记录指针重新定位到上一次mark的位置
      long skip(long n) 将记录指针向前移动n个字符

    2)所有输出节点流的基类OutputStream、Writer

    3) 实现节点流的类

    image.png

    五.处理流

    识别处理流的方法,只要流的构造参数不是一个物理节点,而是一个已存在的流,那这种流一定是处理流。处理流的优点前面已经说过了操作简单,效率更高。

    image.png
    1) 管道流 实现进程之间的通信功能

    2)缓冲流 缓冲流具有缓冲功能,增加缓冲功能后需要flush()才可以将缓冲区的内容写入物理节点,该功能对大幅度的提高了读写效率。

    好多人写代码的时候都喜欢在最后把流fush 然后再close。close是必须的,但是flush有时候是可以不写的,如果你查看了没有缓冲功能的流,你会发现其实它们的flush()方法为空。
    为什么缓冲流可以提升读写效率呢?举个例子,假如你去超市买东西,你是不是会推一个小推车,然后把选好的东西放车里,最后一块儿去付款。你肯定不会拿一件然后去收银台付一次款,拿一件然后付一次。缓冲区就是这个小推车,如果你买的东西多一车不够,可以多来两趟,那个收银台就是物理节点。

    3)转换流
    文件通常被分为文本文件和二进制文件,所有能用记事本打开并看到字符内容(非乱码)的文件称为文本文件(它是特殊的二进制文件),反之则成为二进制文件。
    转换流是把字节流转换成了字符流,如果能确定一个字节流是纯文本文件,那么把它转换成字符流更容易操作。

    相关文章

      网友评论

          本文标题:Java之IO流

          本文链接:https://www.haomeiwen.com/subject/tkyqdftx.html