zoukankan      html  css  js  c++  java
  • Java IO体系综述

    Java IO体系综述

    一、流的概念

      在Java API中,可以从其中读入一个字节序列的对象称作输入流,而可以向其中写入一个字节序列的对象称作输出流。这些字节序列的来源地和目的地可以是文件,而且通常都是文件,但是也可以是网络连接,甚至是内存块。编程语言的I/O类库中使用流这个抽象概念,它代表任何有能力产出数据的数据源对象或者是有能力接收数据的接收端对象。

      Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列。Java的I/O流提供了读写数据的标准方法。任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法。

      Java.io是大多数面向数据流的输入/输出类的主要软件包。此外,Java也对块传输提供支持,在核心库 java.nio中采用的便是块IO。

      流IO的好处是简单易用,缺点是效率较低。块IO效率很高,但编程比较复杂。      

      Java IO模型 : Java的IO模型设计非常优秀,它使用Decorator模式,按功能划分Stream,您可以动态装配这些Stream,以便获得您需要的功能。例如,您需要一个具有缓冲的文件输入流,则应当组合使用FileInputStream和BufferedInputStream。

      简单的理解:流是数据和数据处理过程的统称。

      流操作关心三部分内容:数据源、目标以及过程。

      这些数据源包括:

    • 字节数组

    • String对象

    • 文件

    • “管道”,工作方式与实际管道相似,即,从一段输入,从另一端输出。

    • 一个由其他种类的流组成的序列,以便我们可以将它们收集合并到一个流内。

    • 其他数据源,如Internet连接等。

      总体结构:

    二、流的分类

    • 按流的方向:输入流和输出流

      可以从其中读入一个字节序列的对象称作输入流,而可以向其中写入一个字节序列的对象称作输出流。入和出都是相对于程序本身来说的(不是相当于流本身,因为程序中的“入”,是将流中的数据读取到程序中,对流来说此时是“出”),比如,在程序中使用一个文件保存数据,进行的操作是向流中写入数据保存到文件,此时的流是输出流;从流中读取数据到程序的流称为输入流。

      上面的概念中也反映了该类流的特点:对输入流只能进行读操作,对输出流只能进行写操作。

    • 按数据单位:字节流和字符流

      在电脑磁盘上,所有的数据都是以字节的形式传输和保存,包括图片、视频、文档等数据。一个字节占用8位二进制(8bit),而一个字符根据编码方式的不同,占用的存储空间是不同的。有句话很适合现在:基本的才是万能的。所以字节流能够处理任何类型的数据,而字符流只能处理字符类型的数据。

      在Java中,所有的字节流都以Stream结尾,所有的字符流都含有Reader或Writer

      字节流适合读取音频、图片等二进制文件,字符流适合读取纯文本文件

    • 按功能:节点流和过滤流

      节点流是使用原始的流类进行的操作,而过滤流是在节点流的基础上进行修饰以获得更多的功能,这里使用了装饰器模式。

    三、输入流和输出流层次结构

    • 完整架构

      字节流的顶级父类是抽象类InputStream和OutputStream,输入输出流的层次结构如下图:

      Reader和Writer的层次结构如下图:


      Java类库中的I/O类分成输入和输出两部分,可以在JDK的文档里的类层次结构中查看到。通过继承,任何自InputStream或Reader派生而来的类都含有名为read()的基本方法,用于读取单个字节或字节数组。同样,任何自OutputStream或Writer类派生未来的类都含有名为write()的基本方法,用于写单个字节或者字节数组。但是,我们通常不会用到这些方法,他们之所以存在是因为别的类可以使用它们,以便提供更有用的接口。因此,我们很少使用单一的类来创建流对象,而是通过叠合多个对象来提供所期望的功能(这就是装饰器设计模式)。实际上,Java“流”类库让人迷惑的主要原因就在于:创建单一的结果流,却需要创建多个对象。

      FilterInputStream和FilterOutputStream是用来提供装饰器类接口以控制特定输入流额输出流的两个类,他们的名字不是很直观。FilterInputStream和FilterOutputStream分别自I/O类库中的积累InputStream和OutputStream派生而来,这两个类是装饰器的必要条件(以便能为所有正在被修饰的对象提供通用接口)。

      FilterInputStream类能够完成两件完全不同的事情。其中,DataInputStream允许我们读取不同的基本类型数据以及String对象(所有方法都以“read”开头,例如readByte()、readFloat()等等)。搭配相应的DataInputStream,我们就可以通过数据“流”将基本类型的数据从一个地方迁移到另一个地方。

      其他FilterInputStream类则是在内部修改InputStream的行为方式:是否缓冲,是否保留它所读过的行(允许我们查询行数或设置行数),以及是否把单一字符推回输入流等等。最后两个类看起来更像是为了创建一个编译器(它们被添加进来可能是为了对“用Java构建编译器”实验提供支持),因此我们在一般编程中不会用到它们。

      我们几乎每次都要对输入 进行缓冲——不管我们正在连接的是什么I/O设备,所以,I/O类库把无缓冲输入(而不是缓冲输入)作为特殊情况(或只是方法调用)就显得更加合理了。

    四、Java IO分类介绍

    4.1 字节流

      常用字节流继承结构图: 

    4.1.1字节输入流

      InputStream表示字节输入流的所有类的超类,

      FileInputStream 从文件系统中的某个文件中获得输入字节。

      ByteArrayInputStream 包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪read 方法要提供的下一个字节。关闭ByteArrayInputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何IOException

      PipedInputStream管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。通常,数据由某个线程从PipedInputStream 对象读取,并由其他线程将其写入到相应的PipedOutputStream。不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。管道输入流包含一个缓冲区,可在缓冲区限定的范围内将读操作和写操作分离开。如果向连接管道输出流提供数据字节的线程不再存在,则认为该管道已损坏。

      FilterInputStream 包含其他一些输入流,它将这些流用作其基本数据源,它可以直接传输数据或提供一些额外的功能。

      ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。

      SequenceInputStream 表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。

      BufferedInputStream 为另一个输入流添加一些功能,即缓冲输入以及支持mark 和reset 方法的能力。在创建BufferedInputStream 时,会创建一个内部缓冲区数组。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。mark 操作记录输入流中的某个点,reset 操作使得在从包含的输入流中获取新字节之前,再次读取自最后一次mark 操作后读取的所有字节。

      DataInputStream数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。

      PushbackInputStream 为另一个输入流添加性能,即“推回 (push back)”或“取消读取 (unread)”一个字节的能力。

    4.1.2字节输出流

      OutputStream此抽象类是表示输出字节流的所有类的超类。

      ByteArrayOutputStream此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用toByteArray()toString() 获取数据。关闭ByteArrayOutputStream 无效。

      FileOutputStream文件输出流是用于将数据写入 File 或FileDescriptor 的输出流。

      FilterOutputStream此类是过滤输出流的所有类的超类。

      ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。

      PipedOutputStream可以将管道输出流连接到管道输入流来创建通信管道。管道输出流是管道的发送端。

      BufferedOutputStream该类实现缓冲的输出流。通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。

      DataOutputStream数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。

    4.2 字符流

      常用字符流类继承结构图:

    4.2.1字符输入流

      Reader 用于读取字符流的抽象类。

      BufferedReader从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

      LineNumberReader跟踪行号的缓冲字符输入流。此类定义了方法setLineNumber(int) 和 getLineNumber(),它们可分别用于设置和获取当前行号。

      CharArrayReader此类实现一个可用作字符输入流的字符缓冲区。

      InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

      FileReader用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。

      StringReader其源为一个字符串的字符流。

      PipedReader管道传送的字符输入流。

      FilterReader用于读取已过滤的字符流的抽象类。

      PushbackReader允许将字符推回到流的字符流 reader。

    4.2.2字符输出流

      Writer写入字符流的抽象类。

      BufferedWriter将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

      CharArrayWriter此类实现一个可用作Writer 的字符缓冲区。缓冲区会随向流中写入数据而自动增长。可使用 toCharArray() 和 toString() 获取数据。在此类上调用 close() 无效。

      OutputStreamWriter是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

      FileWriter用来写入字符文件的便捷类。

      PipedWriter管道传送的字符输出流。

      PrintWriter向文本输出流打印对象的格式化表示形式。此类实现在 PrintStream 中的所有 print 方法。它不包含用于写入原始字节的方法,对于这些字节,程序应该使用未编码的字节流进行写入。        

      StringWriter一个字符流,可以用其回收在字符串缓冲区中的输出来构造字符串。关闭 StringWriter 无效。

      FilterWriter用于写入已过滤的字符流的抽象类。

    这里只综述了一下java io大纲,关于java io的详细介绍,大家可关注我后续的博文

    参考文章:

      http://blog.csdn.net/u011596455/article/details/69059499

      http://blog.csdn.net/jianghuxiaojin/article/details/52073031

  • 相关阅读:
    PAT顶级 1015 Letter-moving Game (35分)
    PAT顶级 1008 Airline Routes (35分)(有向图的强连通分量)
    PAT顶级 1025 Keep at Most 100 Characters (35分)
    PAT顶级 1027 Larry and Inversions (35分)(树状数组)
    PAT 顶级 1026 String of Colorful Beads (35分)(尺取法)
    PAT顶级 1009 Triple Inversions (35分)(树状数组)
    Codeforces 1283F DIY Garland
    Codeforces Round #438 A. Bark to Unlock
    Codeforces Round #437 E. Buy Low Sell High
    Codeforces Round #437 C. Ordering Pizza
  • 原文地址:https://www.cnblogs.com/albertrui/p/8358114.html
Copyright © 2011-2022 走看看