Java IO流
1.java IO流概述
1.1 IO流介绍
1.1.1 什么是IO流?
- 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流
- 流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作
1.1.2 java中的IO流列表
分类 | 字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 |
---|---|---|---|---|
抽象基类 | InputStream | OutputStream | Reader | Writer |
访问文件 | FileInputStream | FileOutputStream | FileReader | FileWriter |
访问数组 | ByteArrayInputStream | ByteArrayOutputStream | CharArrayReader | CharArrayWriter |
访问管道 | PipedInputStream | PipedOutputStream | PipedReader | PipedWriter |
访问字符串 | StringReader | StringWriter | ||
缓冲流 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter |
转换流 | InputStreamReader | OutputStreamWriter | ||
对象流 | ObjectInputStream | ObjectOutputStream | ||
抽象基类 | FilterInputStream | FilterOutputStream | FilterReader | FileWriter |
打印流 | PrintStream | |||
推回输入流 | PushbackInputStream | PushbackReader | ||
特殊流 | DataInputStream | DataOutputStream |
1.2 IO流分类
1.2.1 按方向分类
(1)输入流(InputStream):从文件或网络 资源中将数据输入到程序中的流
-
FileInputStream
:从文件读取数据,是最终数据源; -
ServletInputStream
:从HTTP请求读取数据,是最终数据源; -
Socket.getInputStream()
:从TCP连接读取数据,是最终数据源; -
…
(2)输出流(OutStream):从程序中将数据输出到文件或网络的流
1.2.2 按传输单位分类
(1)字符流
- 字符流以字符为单位,根据码表映射字符,一次读入或写入2个字节,只能用于处理文本,用于读写Unicode编码的字符
(2)字节流
- 字节流以字节(8bit)为单位,适用于处理所有类型数据,用于读写ASCII字符和二进制数据
1.2.3 按功能分类
(1)节点流:直接与数据源相连,读入或读出
(2)处理流:处理流和节点流一块使用,在节点流的基础上,再套接一层,套接在节点流上的就是处理流
-
处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接
-
常用的处理流:
-
缓冲流:
BufferedInputStrean
、BufferedOutputStream
、BufferedReader
、BufferedWriter
:增加缓冲功能,避免频繁读写硬盘。
转换流:InputStreamReader
、OutputStreamReader
:实现字节流和字符流之间的转换。
数据流:DataInputStream
、DataOutputStream
:提供将基础数据类型写入到文件中,或者读取出来。对象流:
ObjectInputStream
和ObjectOutputStream
:提供将对象转换成二进制比特流写入到输出流中,也可以将对象从输入流中还原对象数据,构建新对象
-
2.常用 java IO流简单使用
- 以下只给出基础IO流的用法,具体的API使用方法请查看文档
2.1 字符流
2.1.1 FileReader/FileWriter
-
读取单个字符
read()
方法返回范围为0x00-0xffff
正好为两个字节write(int c)
方法的参数值会取低16位
构建char类型字符
public class WriterTest { public static void main(String[] args) throws IOException { try (Reader reader = new FileReader("src/test/resources/text.txt"); Writer writer = new FileWriter("src/test/resources/out.txt")) { int len; while ((len = reader.read()) != -1) { writer.append((char) len); } } catch (Exception e) { e.printStackTrace(); } } }
-
读取多个字符存放到数组中,并使用
read(char[] chars)
方法读取或者将该数组构造成CharSequence
对象,使用append(CharSqquence c,[int start,int end])
方法追加int len; char[] chars = new char[2048]; while ((len = reader.read(chars)) != -1) { writer.append(new String(chars,0,len)); //reader.read(chars);//或者使用 }
2.1.2 BufferedReader/BufferedWriter
-
BufferedWriter使用缓冲区将一串字符先存到缓冲区,当读或写的数据达到一定量, 再自动往文件里进行读写 ,效率相比FileWrter提高很多
-
由于设计时使用装饰者模式对原类的一种功能增强,所以使用方法与FileWriter/Reader相同
-
使用在
finally
块调用close()
关闭流对象之前:- 如果是文件读写完的同时缓冲区刚好装满 , 那么缓冲区会把里面的数据朝目标文件自动进行读或写 , 这种时候你直接调用
close()
方法不会出现问题 ; - 但是如果文件在读写完成时 , 缓冲区没有装满 , 就直接调用
close()
方法 , 这个时候装在缓冲区的数据就不会自动的朝目标文件进行读或写 , 从而造成缓冲区中的这部分数据丢失 , 所以这个是时候就需要在close()
之前先调用flush()
方法 , 手动使缓冲区数据读写到目标文件
public class WriterTest { public static void main(String[] args) throws IOException { try (Reader reader = new BufferedReader(new FileReader("src/test/resources/text.txt")); Writer writer = new BufferedWriter(new FileWriter("src/test/resources/out.txt",true))) { int len; char[] chars = new char[2048]; while ((len = reader.read(chars)) != -1) { writer.append(new String(chars,0,len)); //reader.read(chars); } } catch (Exception e) { e.printStackTrace(); } } }
- 如果是文件读写完的同时缓冲区刚好装满 , 那么缓冲区会把里面的数据朝目标文件自动进行读或写 , 这种时候你直接调用
2.1.3 PiedReader/PiedWriter
-
PiedWriter/Reader
是字符管道输出输入流,两者采用生产者消费者模式,当一方工作未完成时,另一方处于阻塞状态 -
PipedWriter
和PipedReader
的作用是可以通过管道进行线程间的通讯。在使用管道通信时,必须将PipedWriter
和PipedReader
配套使用 -
在使用时可以通过构造方法传入配套字符管道输出输入流来绑定传输方向;也可以通过
connect(配套字符管道输出/输入流对象)
方法,连接配套字符管道输出/输入流- 如果已经连接,第二次连接时会抛出
java.io.IOException
- 可以通过调用
public boolean ready()
方法判断是否已经连接
public class WriterTest { public static void main(String[] args) throws IOException { try(PipedReader reader = new PipedReader(); PipedWriter writer = new PipedWriter( reader)) { //reader.connect(writer); int len; char[] chars = new char[2048]; writer.write("begin"); while ((len = reader.read(chars)) != -1) { writer.append(new String(chars,0,len)); System.out.println((char)reader.read()); //reader.read(chars); } } catch (Exception e) { e.printStackTrace(); } } }
- 如果已经连接,第二次连接时会抛出
2.1.4 InputStreamReader/InputStreamWriter
-
该类通过传入一个字节流对象构造,是字节流与字符流之间的桥梁,能将字节流输出为字符流,并且能为字节流指定字符集,可输出一个个的字符
-
构造时可以传入编码方式
public class WriterTest { public