什么是IO流?
Java中I/O操做主要是指使用java.io包下的内容,进行输入、输出操做。输入也叫作读取数据,输出也叫作做写出数据。java
输入输出(IO): 输入输出是指计算机同任何外部设备之间的数据传递。数组
在IO流里,输入输出分为4步:格式化/解析,缓冲,编码转换和传递。缓存
格式化/解析:在内部数据表示(以字节为单位)与外部数据表示(以字符为单位)之间进行双向转换。例如一个2字节的整数10002,就须要5个字符来表示。编码
缓冲:用于在格式/解析与传递之间缓存字符序列。对于输出,较短的字符序列格式化以后并不立刻输出,而是保存在缓冲区里,待累积到必定规模以后再传递到外部设备。相反,从外部设备读入的大量数据也是先放在缓冲区,而后逐步取出完成输入。默认时,IO流的输入输出都是通过缓冲的,也可让IO流工做在无缓冲模式下。线程
编码转换:是将一种字符表达式转换成另外一种字符表达式。若是格式化产生的字符表达式与外部字符表达式不一样(输出时),或者外部表达式与IO流能解析的表达式不一样(输入时),就必须进行编码转换。如多字节编码与宽字符编码之间的转换等。多数状况下并不须要进行编码转换。code
传递:主要是与外部设备进行通讯。输出时,传递负责将通过格式化、缓冲即编码转换后的字符序列发送到外部设备;输入时,则负责将外部设备抽取数据,为其后进行的编码转换、缓冲及解析提供字符序列。对象
IO流的分类:
根据数据的流向分为:图片
- 输入流 :把数据从其余设备上读取到内存中的流,只能进行读操做。
- 输出流 :把数据从内存 中写出到其余设备上的流,只能进行写操做。
根据数据的类型分为:ip
- 字节流 :以字节为单位,读写数据的流。
- 字符流 :以字符为单位,读写数据的流。
字节流和字符流的区别:内存
- 读写单位不一样:字节流以字节为单位,字符流以字符为单位
- 处理对象不一样:字节流能处理全部类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
- 字节流:一次读入或读出是8位二进制。
- 字符流:一次读入或读出是16位二进制。
分类以后对应的超类(超类也就是父类的意思) | | 输入流 | 输出流 |--|--|--| | 字节流 | 字节输入流 InputStream |字节输出流 OutputStream | | 字符流 | 字符输入流 Reader|字符输出流 Writer|
注: 由这四个类的子类名称基本都是以其父类名做为子类名的后缀。
字节输入流 InputStream:
InputStream
是全部的字节输入流 的父类,它是一个抽象类。ByteArrayInputStream
、StringBufferInputStream
、FileInputStream
是三种基本的介质流,它们分别从Byte 数组
、StringBuffer
、和本地文件
中读取数据。PipedInputStream
是从与其它线程共用的管道中读取数据。ObjectInputStream
和全部FilterInputStream
的子类都是装饰流(装饰器模式的主角)。
FileInputStream fis = new FileInputStream("xxx.txt");//建立流对象 int b; while((b = fis.read()) != -1) { //字节输入流对象fis一次读一个字节 并赋值给b 判断b是否是-1 System.out.println(b); } fis.close();
字节输出流 OutputStream:
OutputStream
是全部的字节输出流 的父类,它是一个抽象类。ByteArrayOutputStream
、FileOutputStream
是两种基本的介质流,它们分别向Byte 数组
、和本地文件
中写入数据。PipedOutputStream
是向与其它线程共用的管道中写入数据。ObjectOutputStream
和全部FilterOutputStream
的子类都是装饰流。
FileOutputStream fos = new FileOutputStream("yyy.txt"); fos.write(100); //写出的是一个int数,可是到文件上的是一个字节,会自动去除前三个8位 fos.write(99); //此时文件yyy.txt中是 dc fos.close();
注意:
1)输出流输出数据在建立输出流对象的时候,若是不存在文件,就建立一个;若是存在就清空该文件数据,而后写入数据。 2)若是想在文件里面追加写入就用new FileOutputStream(String pathName,true)这个构造方法。
字符输入流:
public int read():读取单个字符,并返回成int,若是已到达流的末尾,则返回 -1 public int read(char[] cbuf):将字符读入数组,返回读取的字符数,若是已到达流的末尾,则返回 -1
public static void main(String[] args) throws IOException { FileReader fr = new FileReader("xxx.txt"); //建立字符输入流对象 int c; while((c = fr.read()) != -1) { //经过项目默认的码表一次读取一个字符 System.out.print((char)c); //将c强制类型转换成char } fr.close(); }
字符输出流:
public void write(int c):写入单个字符。 public void write(char[] cbuf):写入字符数组。 public abstract void write(char[] cbuf,int off, int len):写入字符数组的某一部分。cbuf - 字符数组,off - 开始写入字符处的偏移量,len - 要写入的字符数。 public void write(String str):写入字符串。 public void write(String str,int off, int len):写入字符串的某一部分。str - 字符串,off - 相对初始写入字符的偏移量,len - 要写入的字符数 。
节点流: 直接与数据源相连,读入或读出。
经常使用的节点流:
- 父 类 :
InputStream
、OutputStream
、Reader
、Writer
- 文 件 :
FileInputStream
、FileOutputStrean
、FileReader
、FileWriter
文件进行处理的节点流 - 数 组 :
ByteArrayInputStream
、ByteArrayOutputStream
、CharArrayReader
、CharArrayWriter
对数组进行处理的节点流(对应的再也不是文件,而是内存中的一个数组) - 字符串 :
StringReader
、StringWriter
对字符串进行处理的节点流 - 管 道 :
PipedInputStream
、PipedOutputStream
、PipedReader
、PipedWriter
对管道进行处理的节点流
处理流: 处理流和节点流一块使用,在节点流的基础上,再套接一层,套接在节点流上的就是处理流。
经常使用的处理流:
- 缓冲流:
BufferedInputStrean
、BufferedOutputStream
、BufferedReader
、BufferedWriter
增长缓冲功能,避免频繁读写硬盘。 - 转换流:
InputStreamReader
、OutputStreamReader
实现字节流和字符流之间的转换。 - 数据流:
DataInputStream
、DataOutputStream
等-提供将基础数据类型写入到文件中,或者读取出来。
转换流: InputStreamReader
、OutputStreamWriter
要InputStream
或OutputStream
做为参数,实现从字节流到字符流的转换。
序列流: 序列流能够把多个字节输入流整合成一个, 从序列流中读取数据时, 将从被整合的第一个流开始读, 读完一个以后继续读第二个, 以此类推。
1)整合两个输入流SequenceInputStream(InputStream s1, InputStream s2);
public static void demo2() throws FileNotFoundException, IOException { FileInputStream fis1 = new FileInputStream("a.mp3"); FileInputStream fis2 = new FileInputStream("b.mp3"); SequenceInputStream sis = new SequenceInputStream(fis1, fis2); FileOutputStream fos = new FileOutputStream("c.mp3"); //歌曲串烧,c.mp3里面有a.mp3和b.mp3两首歌 int b; while((b = sis.read()) != -1) { fos.write(b); } sis.close(); //sis在关闭的时候,会将构造方法中传入的流对象也都关闭 fos.close(); }
2)整合多个输入流 SequenceInputStream(Enumeration<? extends InputStream> e)
public static void main(String[] args) throws IOException { FileInputStream fis1 = new FileInputStream("a.txt"); FileInputStream fis2 = new FileInputStream("b.txt"); FileInputStream fis3 = new FileInputStream("c.txt"); Vector<FileInputStream> v = new Vector<>(); //建立集合对象 v.add(fis1); //将流对象存储进来 v.add(fis2); v.add(fis3); Enumeration<FileInputStream> en = v.elements(); SequenceInputStream sis = new SequenceInputStream(en); //将枚举中的输入流整合成一个 FileOutputStream fos = new FileOutputStream("d.txt"); int b; while((b = sis.read()) != -1) { fos.write(b); } sis.close(); fos.close(); }