java IO流

时间:2024.5.2
  • 必读
  •  
  • 在 Java 中,每个流都是一个对象。流分为两种:输入流(InputStream)和输出流(OutputStream)。对于输入流,你只要从流当中不停地把字节取出来就是了;而对于输出流,你只要把准备好的字节串传给它就行。
  • 管理

随笔- 143 文章- 23 评论- 58

Java IO流学习总结

Java流操作有关的类或接口:

Java流类图结构:

流的概念和作用

流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。

IO流的分类

·         根据处理数据类型的不同分为:字符流和字节流

·         根据数据流向不同分为:输入流和输出流

字符流和字节流

字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。 字节流和字符流的区别:

·         读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。

·         处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。

结论:只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。

输入流和输出流

对输入流只能进行读操作,对输出流只能进行写操作,程序中需要根据待传输数据的不同特性而使用不同的流。

Java IO流对象

1.输入字节流InputStreamIO 中输入字节流的继承图可见上图,可以看出:

1.     InputStream 是所有的输入字节流的父类,它是一个抽象类。

2.     ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三种基本的介质流,它们分别从Byte 数组、StringBuffer、和本地文件中读取数据。PipedInputStream 是从与其它线程共用的管道中读取数据,与Piped 相关的知识后续单独介绍。

3.     ObjectInputStream 和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)。

2.输出字节流OutputStream

IO 中输出字节流的继承图可见上图,可以看出:

1.     OutputStream 是所有的输出字节流的父类,它是一个抽象类。

2.     ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。PipedOutputStream 是向与其它线程共用的管道中写入数据,

3.     ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流。

3.字节流的输入与输出的对应

图中蓝色的为主要的对应部分,红色的部分就是不对应部分。紫色的虚线部分代表这些流一般要搭配使用。从上面的图中可以看出Java IO 中的字节流是极其对称的。“存在及合理”我们看看这些字节流中不太对称的几个类吧!

1.     LineNumberInputStream 主要完成从流中读取数据时,会得到相应的行号,至于什么时候分行、在哪里分行是由改类主动确定的,并不是在原始中有这样一个行号。在输出部分没有对应的部分,我们完全可以自己建立一个LineNumberOutputStream,在最初写入时会有一个基准的行号,以后每次遇到换行时会在下一行添加一个行号,看起来也是可以的。好像更不入流了。

2.     PushbackInputStream 的功能是查看最后一个字节,不满意就放入缓冲区。主要用在编译器的语法、词法分析部分。输出部分的BufferedOutputStream 几乎实现相近的功能。

3.     StringBufferInputStream 已经被Deprecated,本身就不应该出现在InputStream 部分,主要因为String 应该属于字符流的范围。已经被废弃了,当然输出部分也没有必要需要它了!还允许它存在只是为了保持版本的向下兼容而已。

4.     SequenceInputStream 可以认为是一个工具类,将两个或者多个输入流当成一个输入流依次读取。完全可以从IO 包中去除,还完全不影响IO 包的结构,却让其更“纯洁”――纯洁的Decorator 模式。

5.     PrintStream 也可以认为是一个辅助工具。主要可以向其他输出流,或者FileInputStream 写入数据,本身内部实现还是带缓冲的。本质上是对其它流的综合运用的一个工具而已。一样可以踢出IO 包!System.out 和System.out 就是PrintStream 的实例!

4.字符输入流Reader

在上面的继承关系图中可以看出:

1.     Reader 是所有的输入字符流的父类,它是一个抽象类。

2.     CharReader、StringReader 是两种基本的介质流,它们分别将Char 数组、String中读取数据。PipedReader 是从与其它线程共用的管道中读取数据。

3.     BufferedReader 很明显就是一个装饰器,它和其子类负责装饰其它Reader 对象。

4.     FilterReader 是所有自定义具体装饰流的父类,其子类PushbackReader 对Reader 对象进行装饰,会增加一个行号。

5.     InputStreamReader 是一个连接字节流和字符流的桥梁,它将字节流转变为字符流。FileReader 可以说是一个达到此功能、常用的工具类,在其源代码中明显使用了将FileInputStream 转变为Reader 的方法。我们可以从这个类中得到一定的技巧。Reader 中各个类的用途和使用方法基本和InputStream 中的类使用一致。后面会有Reader 与InputStream 的对应关系。

5.字符输出流Writer

在上面的关系图中可以看出:

1.     Writer 是所有的输出字符流的父类,它是一个抽象类。

2.     CharArrayWriter、StringWriter 是两种基本的介质流,它们分别向Char 数组、String 中写入数据。PipedWriter 是向与其它线程共用的管道中写入数据,

3.     BufferedWriter 是一个装饰器为Writer 提供缓冲功能。

4.     PrintWriter 和PrintStream 极其类似,功能和使用也非常相似。

5.     OutputStreamWriter 是OutputStream 到Writer 转换的桥梁,它的子类FileWriter 其实就是一个实现此功能的具体类(具体可以研究一SourceCode)。功能和使用和OutputStream 极其类似,后面会有它们的对应图。

6.字符流的输入与输出的对应

7.字符流与字节流转换

转换流的特点:

1.     其是字符流和字节流之间的桥梁

2.     可对读取到的字节数据经过指定编码转换成字符

3.     可对读取到的字符数据经过指定编码转换成字节

何时使用转换流?

1.     当字节和字符之间有转换动作时;

2.     流操作的数据需要编码或解码时。

具体的对象体现:

1.     InputStreamReader:字节到字符的桥梁

2.     OutputStreamWriter:字符到字节的桥梁

这两个流对象是字符体系中的成员,它们有转换作用,本身又是字符流,所以在构造的时候需要传入字节流对象进来。

8.File

File类是对文件系统中文件以及文件夹进行封装的对象,可以通过对象的思想来操作文件和文件夹。 File类保存文件或目录的各种元数据信息,包括文件名、文件长度、最后修改时间、是否可读、获取当前文件的路径名,判断指定文件是否存在、获得当前目录中的文件列表,创建、删除文件和目录等方法。

9.RandomAccessFile

该对象并不是流体系中的一员,其封装了字节流,同时还封装了一个缓冲区(字符数组),通过内部的指针来操作字符数组中的数据。 该对象特点:

1.     该对象只能操作文件,所以构造函数接收两种类型的参数:a.字符串文件路径;b.File对象。

2.     该对象既可以对文件进行读操作,也能进行写操作,在进行对象实例化时可指定操作模式(r,rw)

注意:该对象在实例化时,如果要操作的文件不存在,会自动创建;如果文件存在,写数据未指定位置,会从头开始写,即覆盖原有的内容。 可以用于多线程下载或多个线程同时写数据到文件

1流的概念;stream代表的是任何有能力产出数据的数据源,;在Java的IO中,所有的stream(包括In;(1)字节流;表示以字节为单位从stream中读取或往stre;(2)字符流;以Unicode字符为导向的stream,表示以;区别:;Reader和Writer要解决的,最主要的问题;但是,Read和Write并不是取代InputS;以字符为导向

 

1流的概念

stream代表的是任何有能力产出数据的数据源,或是任何有能力接收数据的接收源。流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样,如下图:

在Java的IO中,所有的stream(包括Inputstream和Out stream)都包括两种类型:

(1)字节流

表示以字节为单位从stream中读取或往stream中写入信息,即io包中的inputstream类和outputstream类的派生类。通常用来读取二进制数据,如图象和声音。

(2)字符流

以Unicode字符为导向的stream,表示以Unicode字符为单位从stream中读取或往stream中写入信息。

区别:

Reader和Writer要解决的,最主要的问题就是国际化。原先的I/O类库只支持8位的字节流,因此不可能很好地处理16位的Unicode字符流。Unicode是国际化的字符集(更何况Java内置的char就是16位的Unicode字符),这样加了Reader和Writer之后,所有的I/O就都支持Unicode了。此外新类库的性能也比旧的好。

但是,Read和Write并不是取代InputStream和OutputStream,有时,你还必须同时使用"基于byte的类"和"基于字符的类"。为此,它还提供了两个"适配器(adapter)"类。InputStreamReader负责将InputStream转化成Reader,而OutputStreamWriter则将OutputStream转化成Writer。实际上是通过byte[]和String来关联。在实际开发中出现的汉字问题实际上都是在字符流和字节流之间转化不统一而造成的。

以字符为导向的stream基本上对有与之相对应的以字节为导向的stream。两个对应类实现的功能相同,只是在操作时的导向不同。

如 CharArrayReader和ByteArrayInputStream的作用都是把内存中的一个缓冲区作为InputStream使用,所不同的是前者每次从内存中读取一个字节的信息,而后者每次从内存中读取一个字符。

字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串;而字节流处理单元为1个字节,操作字节和字节数组,可用于任何类型的对象,包括二进制对象,但是不能直接处理Unicode字符。字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的,所以它对多国语言支持性比较好。如果是音频文件、图片、歌曲,就用字节流好点,如果是关系到中文(文本)的,用字符流好点。

2流的层次结构

java将读取数据对象称为输入流,能向其写入的对象叫输出流。

1) 基于字节的输入流

? FileInputStream:把一个文件作为InputStream,从本地文件系统中

读取数据字节,实现对文件的读取操作

? ByteArrayInputStream:把内存中的一个缓冲区作为InputStream使

用,从内存数组中读取数据字节

? ObjectInputStream:对象输入流。从文件中把对象读出来重新建立。

对象必须要实现Serializable接口。对象中的transient和static类型的成员变量不会被读取和写入。

? PipedInputStream:实现了pipe的概念,从线程管道中读取数据字节,

主要在线程中使用。管道输入流是指一个通讯管道的接收端。一个线程通过管道输出流发送数据,而另一个线程通过管道输入流读取数据,这样可实现两个线程间的通讯

? SequenceInputStream:把多个InputStream合并为一个

InputStream,当到达流的末尾时从一个流转到另一个流,“序列输入流”类允许应用程序把几个输入流连续地合并起来,并且使它们像单个输入流一样出现。

? StringBufferInputStream:把一个String对象作为InputStream,

从字符串中读取数据字节

? FilterInputStream:过滤器流java.io.FilterInputStream,过滤器流

即能把基本流包裹起来,提供更多方便的用法。类的构造方法为

FilterInputStream(InputStream),在指定的输入流之上,创建一个输入流过滤器。常用的子类如下:

? BufferedInputStream:缓冲区对数据的访问,以提高效率

? DataInputStream:从输入流中读取基本数据类型,如int、float、

double或者甚至一行文本

? LineNumberInputStream:在翻译行结束符的基础上,维护一个

计数器,该计数器表明正在读取的是哪一行。

? PushbackInputStream:允许把数据字节向后推到流的首部

? System.in

从用户控制台读取数据字节

在System类中, in是InputStream类的静态对象,因此,out和err可以引用PrintStream类的成员方法。如:System.in.read()。

2) 基于字节的输出流

? FileOutputStream:把信息存入文件中

? ByteArrayOutputStream:把信息存入内存中的一个缓冲区中,该类实

现一个以字节数组形式写入数据的输出流

? PipedOutputStream:实现了pipe的概念,主要在线程中使用。管道

输出流是指一个通讯管道的发送端。 一个线程通过管道输出流发送数据, 而另一个线程通过管道输入流读取数据,这样可实现两个线程间的通讯。

? SequenceOutputStream:把多个OutStream合并为一个

OutStream

? FilterOutputStream:类似于FilterInputStream,OutputStream也

提供了过滤器输出流。

? ObjectOutputStream:对象输出流。对象必须要实现Serializable接

口。对象中的transient和static类型的成员变量不会被读取和写入。 ? System.out

输出数据字节到用户控制台

在System类中,out和err是PrintStream类的静态对象,因此,out和err可以引用PrintStream类的成员方法。如:System.out.write (int a)。

3) 基于字符的输入流

? CharArrayReader:与ByteArrayInputStream对应,从字符数组中

读取数据

? StringReader:与StringBufferInputStream对应,从字符数组中读

取数据

? FileReader:与FileInputStream对应,从本地文件系统中读取字符序

列? PipedReader:与PipedInputStream对应,从线程管道中读取字符序

? InputStreamReader:InputStreamReader是从输入流中读取数据,

连接输入流于读取器。如: new InputStreamReader(System.in) ? BufferedReader:缓冲数据的访问,以提高效率

? LineNumberReader(BufferedReader的子类):维护一个计数

器,该计数器表明正在读取的是哪一行。

? FilterReader(抽象类):提供一个类创建过滤器时可以扩展这个类

? PushbackReader(FilterReader的子类):允许把文本数据推回

到读取器的流中。

这些过滤器读取器都可以传入一个Reader作为构造方法的参数。

4) 基于字符的输出流

? CharArrayWrite:与ByteArrayOutputStream对应

? StringWrite:无与之对应的以字节为导向的stream

? FileWrite:与FileOutputStream对应

? PipedWrite:与PipedOutputStream对应

3InputStream类

Inputstream类和Outputstream类都为抽象类,不能创建对象,可以通过子类来实例化。

InputStream是输入字节数据用的类,所以InputStream类提供了3种重载的read方法。Reader也有完全相同的3个read接口。Inputstream类中的常用方法:

1) public abstract int read( ):读取一个byte的数据,返回读到的数据

(高位补0的int类型值),如果返回-1,表示读到了输入流的末尾。

2) public int read(byte b[ ]):读取b.length个字节的数据放到b数

组中。返回值是读取的字节数, 如果返回-1,表示读到了输入流的末尾。该方法实际上是调用下一个方法实现的。

3) public int read(byte b[ ], int off, int len):从输入流中最多读取

len个字节的数据,存放到数组b中,返回实际读取的字节数。如果返回-1,表示读到了输入流的末尾。off指定在 数组b中存放数据的起始偏移位置。

4) public int available( ):返回输入流中可以读取的字节数。注意:若输

入阻塞,当前线程将被挂起,如果InputStream对象调用这个方法的话,它只会返回0,这个方法必须由继承InputStream类的子类对象调用才有用。

5) public long skip(long n):忽略输入流中的n个字节,返回值是实际

忽略的字节数, 跳过一些字节来读取。

6) public int close( ) :我们在使用完后,必须对我们打开的流进行关闭。 7) void mark(int readlimit) :在输入流的当前位置放置一个 标记,如果

读取的字节数多于readlimit设置的值,则流忽略这个标记。在

IutputStream类中实际是一个空实现。

8) void reset() :返回到上一个标记。

9) boolean markSupported() :测试当前流是否支持mark和reset方

法。如果支持,返回true,否则返回false。在IutputStream类中实际是一个空实现。

4OutputSteam类

OutputStream提供了3个write方法来做数据的输出,这个是和

InputStream是相对应的,Writer同样提供了相同的三个write方法。 1) public abstract void write(int b) :先将int转换为byte类型,把

低字节写入到输出流中。

2) public void write(byte b[ ]):将参数b中的字节写到输出流。 3) public void write(byte b[ ], int off, int len) :将参数b的从偏

移量off开始的len个字节写到输出流。

三亿文库3y.uu456.com包含各类专业文献、中学教育、各类资格考试、幼儿教育、小学教育、文学作品欣赏、高等教育、专业论文、外语学习资料、14JAVA输入输出流--字节流篇(什么时候用哪个)等内容。

    在java.io包中, java.io.InputStream 表示字节输入流, java.io.OutputStream表示字节输出流,它们都是抽象类,不能被实例化。InputStream 类提供了一系列和读取数据有关的方法。 

  (1) int read() : 从输入流读取数据,有如下3中重载形式。 

       int read() :从输入流读取一个8位的字节,把它转换为 0~255之间的整数,并返回这一整数。例如,如果读到9, 则返回9, 如果读到的字节为-9,则返回 247,。如果遇到输入流的结尾则返回-1. 

      int read(byte[] b):从输入流读取若干个字节,把它们保存到参数b指定的字节数组中。返回的整数表示读取的字节数。如果遇到输入流结尾,则返回-1. 

      int read(byte[] b, int off, int len):从输入流读取若干个字节,把它们保存到参数b指定的直接数组中。参数off指定在字节数组中开始保存数据的起始下标,参数len指定读取的字节数目。返回的整数表示实际读取的字节数。如果遇到输入流的结尾,则返回-1。 

     以上第一个read方法从输入流读取一个字节,而其余两个read方法从输入流批量读取若干字节。在从文件或键盘读数据时,采用后面两个read可以减少进行物理读文件或键盘的次数,因此提高I/O操作的效率。 

     (2) void close() : 关闭输入流。当完成所有的读操作后,应该关闭输入流。InputStream 类本身的close()方法不执行任何的操作。它的一些子类覆盖了close()方法,在close()方法中释放和流有关的系统资源。 

     (3) int available():返回可以从输入流中读取的字节数目。 

     (4) skip(long n): 从输入流中跳过参数n指定的直接数目。 

     (5) boolean markSupported(), void mark(int readLimit),void reset(): 如果要从流中重复读入数据,可以通过以下方式实现。先用markSupported()方法判断这个流是否支持重复读取数据,如果返回true,则表明可以在流上设置标记。接下来调用 mark(int readLimit)方法从流的当前位置开始设置标记, readLimit 参数指定在流上做了标记的字节数。然后用read()方法读取在标记范围内的字节。最后调用reset()方法,该方法使输入流重新定位到刚才做了标记的起始位置。这样就可以重复读取做过标记的数据了。 


   java.io.Stream 类提供了一系列与写数据有关的方法。 

   (1) void write(int b) :像输出流写入数据,有如下3中重载形式。 
        void write(b) : 向输出流写入一个字节。 

        void write(byte[] b): 把参数b指定的字节数组中的所有字节写到输出流。 

        void write(byte[] int off, int len):把参数b指定的字节数组中的若干字节写到输出流中,参数off指定直接数组的起始下标,从这个位置开始输出由参数len指定数目的字节。 

     以上第一个write方法 向输出流写入一个字节,而其余两个Write方法向输出流批量写入若干字节。在向文件或控制台写数据时,采用后面两个write 方法可以减少进行物理写文件或控制台的次数,因此可以提高I/O操作的效率。 

      (2) void close();:关闭输入流。当完成所有的写操作后,应该关闭输入流。OutputStream类本身的close()方法 不执行任何操作。它的一些子类覆盖了close()方法,释放和流有关的系统资源。 

      (3) void flush():OutputStream 类本身 的flush()方法不执行任何操作,它的一些带有缓冲区的子类(比如BufferOutStream 和 PrintStream类)覆盖了 flush()方法。通过带有缓冲区的输出流写数据时,数据线保存在缓冲区,积累到一定程序才会真正写到输出流中。缓冲区通常用字节数组实现,实际上是指一块内存空间。flush()方法强制把缓冲区的数据写到输出流中。 

更多相关推荐:
java各知识点详细总结

Java基础知识总结写代码1明确需求我要做什么2分析思路我要怎么做1233确定步骤每一个思路部分用到哪些语句方法和对象4代码实现用具体的java语言代码把思路体现出来学习新技术的四点1该技术是什么2该技术有什么...

Java详细总结(精辟版++)

Java总结开始于20xx97092748Java概述Java分类javaSE主要是桌面程序控制台程序开发是java基础javaEE企业级开发网站开发和基于bs模式的编程javaME嵌入式开发手机软件小家电第一...

高手总结java常用API(免费下载)

Java常用API的运用效率及技巧1Java面向对象基本概念2System3StringStringBuffer4数值字符布尔对象与简单类型的操作5ClassClassLoader6JavaIO系统7Java集...

java基础知识总结(超级经典)1

Java基础知识总结写代码1明确需求我要做什么2分析思路我要怎么做1233确定步骤每一个思路部分用到哪些语句方法和对象4代码实现用具体的java语言代码把思路体现出来学习新技术的四点1该技术是什么2该技术有什么...

java知识点总结

Java程序设计基础知识点总结1类首字母大写如果一个类名由多个单词构成那么每个单词的首字母都大写中间不使用任何的连接符比如Person类MemberTest类2方法首字母小写如果一个方法由多个单词构成那么第一个...

Java个人总结(仅供参考)

第一章(1)了解J2SE、J2EE、J2ME?J2SE(Java2StandardEdition):标准版?主要目的是为台式机和工作站提供一个开发和运行的平台。包括标准的Java2SDK、工具、运行时环境和AP…

java基础知识总结(超级经典)

Java基础知识总结超级经典写代码1明确需求我要做什么2分析思路我要怎么做1233确定步骤每一个思路部分用到哪些语句方法和对象4代码实现用具体的java语言代码把思路体现出来学习新技术的四点1该技术是什么2该技...

Java常用类总结

Java常用类总结1Java基本类型的封装类Java的8大基本类型有intlongshortfloatdoublebooleancharbyte对应的封装类是IntegerLongShortFloatDoubl...

毕向东java基础总结(完整版)

克己宽容仁德博学厚黑坚毅稳重Java基础知识总结168克己宽容仁德博学厚黑坚毅稳重Java基础知识总结超级经典写代码1明确需求我要做什么2分析思路我要怎么做1233确定步骤每一个思路部分用到哪些语句方法和对象4...

java面向对象总结

面向对象面向对象是一种思想能让复杂的问题简单化让我们角色从执行者变成指挥者不要知道过程只要知道结果一切皆对象描述一个事物其实就是在描述事物的属性和行为对象的特点在于封装数据数据包含着属性和行为我们用类来描述一个...

Java关键字总结

Java关键字总结21abstractJava关键字abstract关键字可以修改类或方法abstract类可以扩展增加子类但不能直接实例化abstract方法不在声明它的类中实现但必须在某个子类中重写示例pu...

java经典总结(超级经典)

java经典总结超级经典写代码1明确需求我要做什么2分析思路我要怎么做1233确定步骤每一个思路部分用到哪些语句方法和对象4代码实现用具体的java语言代码把思路体现出来学习新技术的四点1该技术是什么2该技术有...

java 总结(38篇)