本文参考:时光孤岛
概念
流是一个抽象的概念,它代表一串数据的集合,当Java程序需要从数据源读取数据时,就需要开启一个到数据源的流。同样,当程序需要输出数据到目的地时,也需要开启一个流。流的创建是为了更方便地处理数据的输入和输出。
分类
处理的数据类型不同:字符流和字节流。
流的方向不同:输入流和输出流。
字符流与字节流的区别
字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表,可以看作是字节流的特殊升级。
(1)读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
(2)处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
(3)字节流在操作的时候本身是不会用到缓冲区的,是文件本身的直接操作的;而字符流在操作的时候下后是会用到缓冲区的,是通过缓冲区来操作文件。
结论:优先选用字节流。首先因为硬盘上的所有文件都是以字节的形式进行传输或者保存的,包括图片等内容。但是字符只是在内存中才会形成的,所以在开发中,字节流使用广泛。
输入流与输出流的区别
输入流只能进行读操作,输出流只能进行写操作。从文件读取数据输入Java程序是输入流,从Java程序输出数据写入到文件是输出流。
IO流类图结构
InputStream
常用类 | 含义 |
---|---|
InputStream |
InputStream 抽象类是字节输入流所有类的超类,它以字节为单位从数据源中读取数据 |
FileInputStream |
以字节为单位从文件中读取数据 |
FilterInputStream |
封装其它的输入流,并为它们提供额外的功能 |
BufferedInputStream |
给输入流提供缓冲功能,提高读取效率 |
DataInputStream |
装饰其它输入流,它允许应用程序以与机器无关方式从底层输入流中读取 Java基本数据类型 |
PushBackInputStream |
可以把读取进来的某些数据重新回退到输入流的缓冲区之中 |
ObjectInputStream |
从输入流读入对象,读取对象信息 |
PipedInputStream |
与其它线程共用的管道中读取数据 |
SequenceInputStream |
合并流 |
StringBufferInputStream |
以字节为单位从字符串中读取数据 |
ByteArrayInputStream |
在内存中创建一个字节数组缓冲区,从输入流读取的数据保存在该字节数组缓冲区中。 |
常用方法 | 含义 |
---|---|
public abstract int read() throws IOExecption |
该方法用于从输入流中读取数据的下一个字节,返回读到的字节值,若遇到流的末尾,返回-1。 |
public int read(byte[] b) throws IOExecption |
该方法用于从输入流中读取b.length个字节的数据,并将数据存储到缓冲区数组b中,返回的是实际读到的字节数。 |
public int read(byte[] b,int off,int len) throws IOExecption |
该方法用于从输入流中读取len个字节的数据,并从数组b的off位置开始写入到这个数组中。 |
public void close() throws IOExecption |
关闭此输入流,并释放与此输入流相关联的所有系统资源。 |
FileInputStream
简介
FileInputStream
是从文件中读取数据,所以我们让它从txt文件中读取数据,然后打印。
public class FileInputStreamTest {
public static void main(String[] args) throws Exception {
//1.得到数据文件
String filePath = "E:\\ExampleTest\\TestText.txt";
File file = new File(filePath);
//2.创建输入流
InputStream inputStream = new FileInputStream(file);
//3.循环读取文件内容,输入流中将最多bytes.length个字节的数据读入一个byte数组中,
//返回的是读取到的字节数。当文件读取到结尾时返回 -1,循环结束。
byte[] bytes = new byte[1024];
int length = 0;
while ((length = inputStream.read(bytes)) != -1) {
System.out.println("Length is " + length);
System.out.println(new String(bytes, 0, length));
}
//4.关闭输入流
inputStream.close();
}
}
如果文件有两个字节内容,则读取时将两个字节读取到bytes中,length等于2,然后再读取一次,因为到达文件末尾,则返回-1,while循环退出,关闭输入流,程序结束。
FilterInputStream
简介
FilterInputStream 只是简单地重写那些将所有请求传递给所包含输入流的 InputStream 的所有方法。FilterInputStream 的子类可进一步重写这些方法中的一些方法,并且还可以提供一些额外的方法和字段。从FilterInputStream类注释可以看出,需要关注的是FilterInputStream的子类,BufferedInputStream,DataInputStream,PushBackInputStream。
FliterInputStream不能直接创建,它的构造方法是protected
。
BufferedInputStream
简介
BufferedInputStream是带缓冲区的输入流,默认缓冲区大小是8M,能够减少访问磁盘的次数,提高文件读取性能。
我们从InputStream中读取数据时,一般都会是磁盘io,或者网络io,这都是耗费大量时间的操作,比如我们现在从文件读取20个字节,过一会又从文件读取20个字节,这就是两次io,浪费资源,有了BufferedInputStream,就解决这个两次io的问题,输入流在read时,干脆多读一部分数据进来,放在内存里,等你每次操作流的时候,读取的数据直接从内存中就可以拿到,这就减少了io次数,提升效率。
public class BufferedInputStreamTest{
public static void main(String[] args) throws Exception{
//1.得到数据文件
String filePath = "E:\\ExampleTest\\TestText.txt";
File file = new File(filePath);
//2.创建缓冲输入流
BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(file));
//3.循环读取文件内容,输入流中将最多bytes.length个字节的数据读入一个byte数组中,
//返回的是读取到的字节数。当文件读取到结尾时返回 -1,循环结束。
byte[] bytes = new byte[1024];
int length = 0;
while ((length = inputStream.read(bytes)) != -1) {
System.out.println("Length is " + length);
System.out.println(new String(bytes, 0, length));
}
//4.关闭输入流
inputStream.close();
}
}
DataInputStream
与DataOutputStream
简介
DataInputStream 是用来装饰其它输入流,DataOutputStream是用来修饰其他输出流,它允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用DataOutputStream(数据输出流)写入数据然后由DataInputStream(数据输入流)读取数据。
public class DataInputStreamTest {
public static void main(String[] args) throws Exception{
//1.得到数据文件
String filePath = "E:\\ExampleTest\\TestText.txt";
File file