我们编写的程序除了自身会定义一些数据信息外,经常还会引用外界的数据,或是将自身的数据发送到外界。比如,我们编写的程序想读取一个文本文件,又或者我们想将程序中的某些数据写入到一个文件中。这时我们就要使用输入与输出。
什么是输入(read):输入是一个从外界进入到程序的方向,通常我们需要“读取”外界的数据时,使用输入。所以输入是用来读取数据的。
什么是输出(write):输出是一个从程序发送到外界的方向,通常我们需要”写出”数据到外界时,使用输出。所以输出是用来写出数据的。
InputStream是所有字节输入流的父类,其定义了基础的读取方法,常用的方法如下:
1.int read()
:读取一个字节,以int形式返回,该int值的”低八位”有效,若返回值为-1则表示EOF。
2.int read(byte[] d)
:尝试最多读取给定数组的length个字节并存入该数组,返回值为实际读取到的字节量。
OutputStream是所有字节输出流的父类,其定义了基础的写出方法,常用的方法如下:
1.void write(int d)
:写出一个字节,写的是给定的int的”低八位”。
2.void write(byte[] d)
:将给定的字节数组中的所有字节全部写出。
文件流
FileOutputStream
java.io.FileOutputStream
:文件字节输出流,用于将数据写入到文件中的流,该流是一个低级流。低级流特点:
数据的来源和去向是明确的,真实负责“搬运”数据的流。
1 | public class FOSDemo { |
FileInputStream
java.io.FileInputStream
:低级流,可以从文件中读取字节(操作过程和RandomAccessFile相似)。
1 | public class FISDemo { |
复制
使用文件流的形式复制文件。
1 | public class CopyDemo1 { |
缓冲流
在读取数据时若以字节为单位读取数据,会导致读取次数过于频繁从而大大的降低读取效率。为此我们可以通过提高一次读取的字节数量减少读写次数来提高读取的效率。
1.BIS
:是一个处理流,该流为我们提供了缓冲功能。
2.BOS
:与缓冲输入流相似,在向硬件设备做写出操作时,增大写出次数无疑也会降低写出效率,为此我们可以使用缓冲输出流来一次性批量写出若干数据减少写出次数来提高写 出效率。
3.BufferedInputStream
是缓冲字节输入流。其内部维护着一个缓冲区(字节数组),使用该流在读取一个字节时,该流会尽可能多的一次性读取若干字节并存入缓冲区,然后逐一的将字节返回,直到缓冲区中的数据被全部读取完毕,会再次读取若干字节从而反复。这样就减少了读取的次数,从而提高了读取效率。
4.BufferedOutputStream
缓冲输出流内部也维护着一个缓冲区,每当我们向该流写数据时,都会先将数据存入缓冲区,当缓冲区已满时,缓冲流会将数据一次性全部写出。
BIS和BOS
BufferedInputStream
与BufferedOutputStream
(BIS和BOS):缓冲字节输入流,缓冲字节输出流.这是一对高级流,作用是可以提高读写效率.(作用类似于字节数组)。
1 | public class CopyDemo2 { |
flush
void flush()
,缓冲流都提供了flush的实现。作用是强制将现有缓冲数组中的数据一次性写出。避免了因缓冲数组中数据不够而导致文件内容为空的问题。频繁调用该方法会提高写出次数从而降低写出效率,但是当我们需要有写出数据即时性的时候就要使用。
1 | public class BosDemo { |
对象流
对象是存在于内存中的。有时候我们需要将对象保存到硬盘上,又有时我们需要将对象传输到另一台计算机上等等这样的操作。这时我们需要将对象转换为一个字节序列,而这个过程就称为对象序列化。相反,我们有这样一个字节序列需要将其转换为对应的对象,这个过程就称为对象的反序列化。
1.java.io.ObjectOutputStream
:高级流,功能是将给定的一个对象转换为一组字节,然后通过其处理的流将字节写出。
2.java.io.ObjectInputStream
:高级流,可以进行对象的反序列化。将 一组字节还原回对象,前提是这一组字节必须是由ObjectOutputStream将一个对象序列化后的字节
读写对象一般用于:保存现有对象到硬盘上;在网络中传输对象。
以下Person类用于测试对象流读写对象:
1 | public class Person implements Serializable{ |
对象→字节
1 | public class OOSDemo { |
字节→对象
1 | public class OISDemo { |
字符流
Reader
是所有字符输入流的父类,而Writer
是所有字符输出流的父类。字符流是以字符(char)为单位读写数据的。一次处理一个unicode。字符流都是高级流,其底层都是依靠字节流进行读写数据的,所以底层仍然是基于字节读写数据的。
Reader
的常用方法:
1.int read()
:读取一个字符,返回的int”值低16”位有效。
2.int read(char[] chs)
:从该流中读取一个字符数组length个字符并存入该数组,返回值为实际读取到的字符量。
Writer
的常用方法:
1.void write(int c)
:写出一个字符,写出给定int值”低16”位表示的字符。
2.void write(char[] chs)
:将给定字符数组中所有字符写出。
3.void write(String str)
:给定的字符串写出。
4.void write(char[] chs,int offset,int len)
:将给定的字符数组中从offset处开始连续的len个字符写出。
Writer
Writer
字符输出流,特点:以字符为单位写出数据。
OutputStreamWriter
:字符流的一个常用实现类。特点是可以按照指定的字符集将给定的字符串转换为对应的字节后写出。
1 | public class OSWDemo { |
Reader
Reader
字符输入流 特点:以字符为单位读取数据
InputStreamReader
是其常用实现类,作用是可以按照指定的字符集读取字符。
1 | public class ISRDemo { |
转码
转码:比如将UTF-8编码的文本文件转换为GBK编码的文本文件
原理:使用UTF-8编码将每一个字符读取出来,再以GBK编码将字符写入另一个文件即可。
1 | public class ChangeCharsetDemo { |
PrintWriter
缓冲字符输出流,特点是可以以行为单位写出字符串并且该流还具备自动行刷新功能。
传统的缓冲字符输出流是BufferedWriter
.由于PrintWriter
在创建的时候内部使用了该流,并且PrintWriter
还具有自动行刷新,所以比较常用。
PrintWriter
提供了若干构造方法,可以方便快速创建。
1 | public class PWDemo { |
PrintWriter
处理其他流的形式:
1 | public class PWDemo2 { |
BufferedReader
java.io.BufferedReader
:缓冲字符输入流 特点:以行为单位读取字符串。
1 | public class BRDemo { |