`
寂地流年
  • 浏览: 26697 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

I/O类体系

阅读更多

     在JDK API中,基础的IO类都位于java.io包,而新实现的IO类则位于一系列以java.nio开头的包名中,这里首先介绍java.io包中类的体系结构。

按照前面的说明,流是有方向的,则整个流的结构按照流的方向可以划分为两类:

1、输入流:

该类流将外部数据源的数据转换为流,程序通过读取该类流中的数据,完成对于外部数据源中数据的读入。

2、输出流:

该类流完成将流中的数据转换到对应的数据源中,程序通过向该类流中写入数据,完成将数据写入到对应的外部数据源中。

而在实际实现时,由于JDK API历史的原因,在java.io包中又实现了两类流:字节流(byte stream)和字符流(char stream)。这两种流实现的是流中数据序列的单位,在字节流中,数据序列以byte为单位,也就是流中的数据按照一个byte一个byte的顺序实现成流,对于该类流操作的基本单位是一个byte。

      而对于字节流,数据序列以char为单位,也就是流中的数据按照一个char一个插入的顺序实现成流,对于该类流操作的基本单位是一个char。

另外字节流是从JDK1.0开始加入到API中的,而字符流则是从JDK1.1开始才加入到API中的,对于现在使用的JDK版本来说,这两类流都包含在API的内部。在实际使用时,字符流的效率要比字节流高一些。

      在实际使用时,字符流中的类基本上和字节流中的类对应,所以在开始学习IO类时,可以从最基础的字节流开始学习。

      在SUN设计JDK的IO类时,按照以上的分类,为每个系列的类设计了一个父类,而实现具体操作的类都作为该系列类的子类,则IO类设计时的四个体系中每个体系中对应的父类分别是:

 

字节输入流InputStream

 

     该类是IO编程中所有字节输入流的父类,熟悉该类的使用将对使用字节输入流产生很大的帮助,下面做一下详细的介绍。

按照前面介绍的流的概念,字节输入流完成的是按照字节形式构造读取数据的输入流的结构,每个该类的对象就是一个实际的输入流,在构造时由API完成将外部数据源转换为流对象的操作,这种转换对程序员来说是透明的。在程序使用时,程序员只需要读取该流对象,就可以完成对于外部数据的读取了。

InputStream是所有字节输入流的父类,所以在InputStream类中包含的每个方法都会被所有字节输入流类继承,通过将读取以及操作数据的基本方法都声明在InputStream类内部,使每个子类根据需要覆盖对应的方法,这样的设计可以保证每个字节输入流子类在进行实际使用时,开放给程序员使用的功能方法是一致的。这样将简化IO类学习的难度,方便程序员进行实际的编程。

默认情况下,对于输入流内部数据的读取都是单向的,也就是只能从输入流从前向后读,已经读取的数据将从输入流内部删除掉。如果需要重复读取流中同一段内容,则需要使用流类中的mark方法进行标记,然后才能重复读取。这种设计在使用流类时,需要深刻进行体会。

在InputStream类中,常见的方法有:

a、available方法

public int available() throws IOException

该方法的作用是返回当前流对象中还没有被读取的字节数量。也就是获得流中数据的长度。

假设初始情况下流内部包含100个字节的数据,程序调用对应的方法读取了一个字节,则当前流中剩余的字节数量将变成99个。

另外,该方法不是在所有字节输入流内部都得到正确的实现,所以使用该方法获得流中数据的个数是不可靠的。

b、close方法

public void close() throws IOException

该方法的作用是关闭当前流对象,并释放该流对象占用的资源。

在IO操作结束以后,关闭流是进行IO操作时都需要实现的功能,这样既可以保证数据源的安全,也可以减少内存的占用。

c、markSupported方法

public boolean markSupported()

该方法的作用是判断流是否支持标记(mark)。标记类似于读书时的书签,可以很方便的回到原来读过的位置继续向下读取。

d、reset方法

public void reset() throws IOException

该方法的作用是使流读取的位置回到设定标记的位置。可以从该位置开始继续向后读取。

e、mark方法

public void mark(int readlimit)

为流中当前的位置设置标志,使得以后可以从该位置继续读取。变量readlimit指设置该标志以后可以读取的流中最大数据的个数。当设置标志以后,读取的字节数量超过该限制,则标志会失效。

f、read方法

read方法是输入流类使用时最核心的方法,能够熟练使用该方法就代表IO基本使用已经入门。所以在学习以及后期的使用中都需要深刻理解该方法的使用。

在实际读取流中的数据时,只能按照流中的数据存储顺序依次进行读取,在使用字节输入流时,读取数据的最小单位是字节(byte)。

另外,需要注意的是,read方法是阻塞方法,也就是如果流对象中无数据可以读取时,则read方法会阻止程序继续向下运行,一直到有数据可以读取为止。

read方法总计有三个,依次是:

public abstract int read() throws IOException

该方法的作用是读取当前流对象中的第一个字节。当该字节被读取出来以后,则该字节将被从流对象中删除,原来流对象中的第二个字节将变成流中的第一个字节,而使用流对象的available方法获得的数值也将减少1。如果需要读取流中的所以数据,只要使用一个循环依次读取每个数据即可。当读取到流的末尾时,该方法返回-1。该返回值的int中只有最后一个字节是流中的有效数据,所以在获得流中的数值时需要进行强制转换。返回值作成int的目的主要是处理好-1的问题。

由于该方法是抽象的,所以会在子类中被覆盖,从而实现最基础的读数据的功能。

public int read(byte[] b) throws IOException

该方法的作用是读取当前流对象中的数据,并将读取到的数据依次存储到数组b(b需要提前初始化完成)中,也就是把当前流中的第一个字节的数据存储到b[0],第二个字节的数据存储到b[1],依次类推。流中已经读取过的数据也会被删除,后续的数据会变成流中的第一个字节。而实际读取的字节数量则作为方法的返回值返回。

public int read(byte[] b, int off, int len) throws IOException

该方法的作用和上面的方法类似,也是将读取的数据存储到b中,只是将流中的第一个数据存储到b中下标为off的位置,最多读取len个数据,而实际读取的字节数量则作为方法的返回值返回。

g、skip方法

public long skip(long n) throws IOException

该方法的作用是跳过当前流对象中的n个字节,而实际跳过的字节数量则以返回值的方式返回。

跳过n个字节以后,如果需要读取则是从新的位置开始读取了。使用该方法可以跳过流中指定的字节数,而不用依次进行读取了。

从流中读取出数据以后,获得的是一个byte数组,还需要根据以前的数据格式,实现对于该byte数组的解析。

由于InputStream类是字节输入流的父类,所以该体系中的每个子类都包含以上的方法,这些方法是实现IO流数据读取的基础。

字节输出流OutputStream

该类是所有的字节输出流的父类,在实际使用时,一般使用该类的子类进行编程,但是该类内部的方法是实现字节输出流的基础。

该体系中的类完成把对应的数据写入到数据源中,在写数据时,进行的操作分两步实现:第一步,将需要输出的数据写入流对象中,数据的格式由程序员进行设定,该步骤需要编写代码实现;第二步,将流中的数据输出到数据源中,该步骤由API实现,程序员不需要了解内部实现的细节,只需要构造对应的流对象即可。

在实际写入流时,流内部会保留一个缓冲区,会将程序员写入流对象的数据首先暂存起来,然后在缓冲区满时将数据输出到数据源。当然,当流关闭时,输出流内部的数据会被强制输出。

字节输出流中数据的单位是字节,在将数据写入流时,一般情况下需要将数据转换为字节数组进行写入。

在OutputStream中,常见的方法有:

a、close方法

public void close() throws IOException

该方法的作用是关闭流,释放流占用的资源。

b、flush方法

public void flush() throws IOException

该方法的作用是将当前流对象中的缓冲数据强制输出出去。使用该方法可以实现立即输出。

c、write方法

write方法是输出流中的核心方法,该方法实现将数据写入流中。在实际写入前,需要实现对应的格式,然后依次写入到流中。写入流的顺序就是实际数据输出的顺序。

write方法总计有3个,依次是:

public abstract void write(int b) throws IOException

该方法的作用是向流的末尾写入一个字节的数据。写入的数据为参数b的最后一个字节。在实际向流中写数据时需要按照逻辑的顺序进行写入。该方法在OutputStream的子类内部进行实现。

public void write(byte[] b) throws IOException

该方法的作用是将数组b中的数据依次写入当前的流对象中。

public void write(byte[] b, int off, int len) throws IOException

该方法的作用是将数组b中从下标为off(包含)开始,后续长度为len个的数据依次写入到流对象中。

在实际写入时,还需要根据逻辑的需要设定byte数值的格式,这个根据不同的需要实现不同的格式。

 

字符输入流Reader

 

     字符输入流体系是对字节输入流体系的升级,在子类的功能上基本和字节输入流体系中的子类一一对应,但是由于字符输入流内部设计方式的不同,使得字符输入流的执行效率要比字节输入流体系高一些,在遇到类似功能的类时,可以优先选择使用字符输入流体系中的类,从而提高程序的执行效率。

Reader体系中的类和InputStream体系中的类,在功能上是一致的,最大的区别就是Reader体系中的类读取数据的单位是字符(char),也就是每次最少读入一个字符(两个字节)的数据,在Reader体系中的读数据的方法都以字符作为最基本的单位。

Reader类和InputStream类中的很多方法,无论声明还是功能都是一样的,但是也增加了两个方法,依次介绍如下:

a、read方法

public int read(CharBuffer target) throws IOException

该方法的作用是将流内部的数据依次读入CharBuffer对象中,实际读入的char个数作为返回值返回。

b、ready方法

public boolean ready() throws IOException

该方法的作用是返回当前流对象是否准备完成,也就是流内部是否包含可以被读取的数据。

其它和InputStream类一样的方法可以参看上面的介绍。

字符输出流Writer

字符输出流体系是对字节输出流体系的升级,在子类的功能实现上基本上和字节输出流保持一一对应。但由于该体系中的类设计的比较晚,所以该体系中的类执行的效率要比字节输出流中对应的类效率高一些。在遇到类似功能的类时,可以优先选择使用该体系中的类进行使用,从而提高程序的执行效率。

Writer体系中的类和OutputStream体系中的类,在功能上是一致的,最大的区别就是Writer体系中的类写入数据的单位是字符(char),也就是每次最少写入一个字符(两个字节)的数据,在Writer体系中的写数据的方法都以字符作为最基本的操作单位。

Writer类和OutputStream类中的很多方法,无论声明还是功能都是一样的,但是还是增加了一些方法,依次介绍如下:

a、append方法

将数据写入流的末尾。总计有3个方法,依次是:

public Writer append(char c) throws IOException

该方法的作用和write(int c)的作用完全一样,既将字符c写入流的末尾。

public Writer append(CharSequence csq) throws IOException

该方法的作用是将CharSequence对象csq写入流的末尾,在写入时会调用csq的toString方法将该对象转换为字符串,然后再将该字符串写入流的末尾。

public Writer append(CharSequence csq, int start, int end)
throws IOException

该方法的作用和上面的方法类似,只是将转换后字符串从索引值为start(包含)到索引值为end(不包含)的部分写入流中。

b、write方法

除了基本的write方法以外,在Writer类中又新增了两个,依次是:

public void write(String str) throws IOException

该方法的作用是将字符串str写入流中。写入时首先将str使用getChars方法转换成对应的char数组,然后实现依次写入流的末尾。

public void write(String str, int off, int len)
throws IOException

该方法的作用是将字符串str中索引值为off(包含)开始,后续长度为len个字符写入到流的末尾。

使用这两个方法将更方便将字符串写入流的末尾。

其它和OutputStream类一样的方法可以参看上面的介绍。

    

小结

 

     在实际使用IO类时,根据逻辑上的需要,挑选对应体系中的类进行实际的使用,从而实现程序中IO的相关功能。

熟悉了IO类的体系以后,就可以首先熟悉基本的IO类的使用,然后再按照IO类体系中相关类的使用方式逐步去了解相关的IO类的使用,从而逐步熟悉java.io包中类的使用,然后再掌握IO编程。

在实际使用时,一般都使用这4个类中对应的子类,每个子类完成相关的功能。对于这些子类,也可以根据这些类是否直接连接数据源,将这些IO类分类为:

1、实体流

指直接连接数据源的IO流类

2、装饰流

指不直接连接数据源,而是建立在其它实体流对象的基础之上。

下面IO类的使用中将分别介绍这些体系中的类。在实际使用时也应该根据流属于实体流还是装饰流进行不同的使用。


 

分享到:
评论

相关推荐

    计算机组成与体系结构期末复习题

    1.假定基准程序在某计算机上的运行时间为 100s,其中 90s 为 CPU
时间,其余为 I/O 时间。若 CPU速度提高 50%,I/O速度不变,则运行基准程序 A 所耗费的时间是()。 
A. 55s
B.60s C.65S D.70S 答案:D 解析:...

    丹纳赫传动推出新一代 SQIO SynqNet I/O 模块

    丹纳赫传动(Danaher Motion)公司新近推出了 SQIO(SynqNet I/O)接口板,这是目前唯一可以让大批量机器制造商将复杂的高性能传动定制模拟和/或数字 I/O 硬件无缝集成到 SynqNet 网络体系结构中的 SynqNet I/O 接口...

    利用LabWindows_CVI的VISA体系对仪器进行I_O的操作

    利用LabWindows_CVI的VISA体系对仪器进行I_O的操作

    如何选用硬件在环测试系统 I/O接口

    高性能模块化的I/O接口是构建成功硬件在环测试系统所必须的。硬件在环(HIL)测试系统体系结构教程讨论了多种硬件在环测试系统体系结构和用于实现的实时处理技术。本教程讨论了多种I/O接口选项,能够用于实时处理器...

    java_I/ODemo

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

    嵌入式系统-硬件与软件架构(正版)

     6.1.4 并行I/O示例3(并行输出和图形I/O)   6.1.5 并行和串行I/O示例4(网络与通信:以太网)   6.2 I/O组件的接口   6.2.1 I/O设备与嵌入式电路板的接口   6.2.2 I/O控制器与主CPU的接口   6.3 I/O和...

    嵌入式系统/ARM技术中的高带宽I/O总线解决方案支持新一代嵌入式系统

    微处理器的性能每18个月便提高一倍,而I/O总线体系结构的性能每3年才可提高一倍。这样,I/O瓶颈就妨碍了处理器与内存子系统领域的革新,进而限制了整体系统性能。除了复杂化的处理器系统设计,系统还连接了众多传统...

    C++流类体系与文件操作

    通过本章学习,应理解I/O流、流类与流类体系的概念,掌握流的输入/输出控制格式。了解C++有关文件的概念及文件的使用方法,理解文件流类体系结构,掌握实现文件操作的成员函数的使用方法,学会文本文件的打开、读/...

    嵌入式系统/ARM技术中的嵌入系统中闪存设备I/O软件的设计与实现

    闪存作为广泛使用的嵌入式存储设备,其管理技术和访问方式经历了一个由开发人员直接控制到由操作系统的I/O软件间接控制的过程。然而目前现有的这些闪存管理方案都不能提供一种方便、统一且移植性好的I/O软件接口,...

    IO端口和IO内存详解

    外设寄存器也称为“I/O端口”,通常包括:控制寄存器、状态寄存器和数据寄存器三大类,而且一个外设的寄存器通常被连续地编址。CPU对外设IO端口物理地址的编址方式有两种:一种是I/O映射方式(I/O-mapped),另一种...

    学生(班级)信息管理系统7

    5.4 灵活的系统体系构架: 18 5.5 产品化开发,降低用户成本: 19 6系统流程分析 20 7功能模块 21 8各模块具体功能 22 8.1、用户管理 23 8.2、学生档案管 24 8.3、班级管理 25 8.4、课程管理 26 8.5、学成绩管理 ...

    HP AlphaServer GS1280系统配置手册

    GS1280最低可以支持2个主频为1.15GHz的Alpha 21364(EV7)微处理器和每个处理器8GB的主内存(FRS)(受体系结构的限制最高每个处理器为32GB)同时它还可支持PCI/PCI-X和AGP I/O选件。该款系统能够提供每个处理器12.3GB/s的...

    选择硬件在环(HIL)测试系统I/O接口

    高性能模块化的I/O接口是构建成功硬件在环测试系统所必须的。硬件在环(HIL)测试系统体系结构教程讨论了多种硬件在环测试系统体系结构和用于实现的实时处理技术。本教程讨论了多种I/O接口选项,能够用于实时处理器...

    操作系统简答题试题及答案.doc

    1. I/O软件一般分为哪几个层次? 从硬件层到用户层分为中断处理程序;设备驱动程序;与设备无关的I/O软件;用户 空间的I/O软件等4层。 2. 操作系统有哪些基本类型? 基本的操作系统类型有三种:多道批处理操作系统,...

    x86 x64体系探索及编程part1

    145 9.4 SMI 的Back-to-Back 响应 147 9.5 SMM 里开启保护模式 147 9.6 SMM 的版本 148 9.7 I/O 指令的重启及Halt 重启 151 9.8 SMM 的退出 152 9.9 SMBASE 的重定位. 153 9.10 SMI 处理程序的初始化 154 9.11 SMM ...

    深入理解Linux内核中文第三版——第13章 IO体系结构和设备驱动程序

    《深入理解linux内核中文第三版》,高清晰扫描,真正中文第三版,对Linux 2.6内核进行了详细而细致的讲解。由于之前的压缩包分卷太多,现提供每一章的单独下载文件。100%高清晰第三版!

    疯狂内核之——虚拟文件系统

    目录 1 虚拟文件系统概述 5 1.1 通用文件模型 7 1.2 VFS所处理的系统...6 直接I/O与异步I/O 391 6.1 直接I/O 391 6.2 异步I/O 393 6.2.1 Linux 2.6中的异步I/O 394 6.2.2 异步I/O环境 394 6.2.3 提交异步I/O操作 395

    UNIX环境高级编程_第二版中文

    第3章 文件I/O  3.1 引言  3.2 文件描述符  3.3 open函数  3.4 creat函数  3.5 close函数  3.6 lseek函数  3.7 read函数  3.8 write函数  3.9 I/O的效率  3.10 文件共享  3.11 原子操作  ...

    计算机体系结构试题及答案

    6.5.1 I/O和Cache数据一致性 6.5.2 DMA和虚拟存储器 6.6 I/O系统设计 6.7 小结习题六第七章 多处理机 7.1 引言 7.1.1 并行计算机体系结构的分类 7.1.2 通信模型和存储器的结构模型 7.1.3 通信...

Global site tag (gtag.js) - Google Analytics