JAVA_IO流
1.IO流
- 数据源 data source,提供数据的原始媒介。常见的数据源有:数据库、文件、其他程
序、内存、网络连接、IO 设备。 - 数据源分为:源设备、目标设备。
源设备:为程序提供数据,一般对应输入流。
目标设备:程序数据的目的地,一般对应输出流。
- 流的概念
流是一个抽象、动态的概念,是一连串连续动态的数据集合。
对于输入流而言,数据源就像水箱,流(stream)就像水管中流动着的水流,程序就是我们最终的用户。我们通过流(A Stream)将数据源(Source)中的数据(information)输送到程序(Program)中。
对于输出流而言,目标数据源就是目的地(dest),我们通过流(A Stream)将程序(Program)中的数据(information)输送到目的数据源(dest)中。 - 按流的方向分类:
输入流:数据流向是数据源到程序(以InputStream、Reader结尾的流)。
输出流:数据流向是程序到目的地(以 OutPutStream、Writer 结尾的流)。
- 按处理的数据单元分类:
字节流:以字节为单位获取数据,命名上以Stream结尾的流一般是字节流,如FilelnputStream、FileQutputStream.
字符流:字符为单位获取数据,命名上以 Reader/Writer 结尾的流一般是字符流,如 FileReader、FileWriter。
- 按处理对象不同分类:
节点流:可以直接从数据源或目的地读写数据,如 FilelnputStream、FileReader、 DatalnputStream等。
处理流:不直接连接到数据源或目的地,是”处理流的流”。通过对其他流的处理提高程序的性能,如 BufferedInputStream、BufferedReader等。
2.代码
package obj;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class ReadFile {
public static void main(String[] args) {
copyFile2();
}
public static void readFile() {//原始版本
FileInputStream fis = null;
try {
fis = new FileInputStream("E:/IDEA/IdeaProjects/Java/HelloWorld/HelloWorld/src/b.txt");
StringBuilder sb = new StringBuilder();
int temp = 0;
while ((temp = fis.read()) != -1) {
sb.append((char) temp);
}
System.out.println(sb);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
if (fis != null)
fis.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public static void readFile2() {//使用语法糖,自动关闭文件的新版本
try (FileInputStream fis = new FileInputStream("E:/IDEA/IdeaProjects/Java/HelloWorld/HelloWorld/src/b.txt");) {
StringBuilder sb = new StringBuilder();
int temp = 0;
while ((temp = fis.read()) != -1) {
sb.append((char) temp);
}
System.out.println(sb);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void writeFile() {//写文件同理
try (FileOutputStream fis = new FileOutputStream("E:/IDEA/IdeaProjects/Java/HelloWorld/HelloWorld/src/b.txt");) {
fis.write("abc".getBytes(StandardCharsets.UTF_8));
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void copyFile() {//一字节一字节拷贝
try (FileInputStream fis = new FileInputStream("E:/IDEA/IdeaProjects/Java/HelloWorld/HelloWorld/src/b.txt");
FileOutputStream fos = new FileOutputStream("E:/IDEA/IdeaProjects/Java/HelloWorld/HelloWorld/src/b2.txt");) {
int temp = 0;
while ((temp = fis.read()) != -1) {
fos.write(temp);
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void copyFile2() {//利用缓存高效率拷贝
try (FileInputStream fis = new FileInputStream("E:/IDEA/IdeaProjects/Java/HelloWorld/HelloWorld/src/b.txt");
FileOutputStream fos = new FileOutputStream("E:/IDEA/IdeaProjects/Java/HelloWorld/HelloWorld/src/b2.txt");) {
byte[] buffer = new byte[10];
int bytesRead = 0;
while ((bytesRead = fis.read(buffer)) != -1) {
System.out.println(bytesRead);//3
fos.write(buffer, 0, bytesRead);
}
System.out.println(bytesRead);//-1
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
3.IO流体系介绍
-
文件字符流
前面介绍的文件字节流可以处理所有的文件,但是字节流不能很好的处理Unicode字符,经常会出现“乱码”现象。所以,我们处理文本文件,一般可以使用文件字符流,它以字符为单位进行操作。 -
缓冲字节流
Java缓冲流本身并不具有IO流的读取与写入功能,只是在别的流(节点流或其他处理流)上加上缓冲功能提高效率,就像是把别的流包装起来一样,因此缓冲流是一种处理流(包装流)。
当对文件或者其他数据源进行频繁的读写操作时,效率比较低,这时如果使用缓冲流就能够更高效的读写信息。因为缓冲流是先将数据缓存起来,然后当缓存区存满后或者手动刷新时再一次性的读取到程序或写入目的地。
因此,缓冲流还是很重要的,我们在10操作时记得加上缓冲流来提升性能。
BufferedInputStream和BufferedOutputStream这两个流是缓冲字节流,通过内部缓存数组来提高操作流的效率。 -
缓冲字符流
BufferedReader/BufferedWriter增加了缓存机制,大大提高了读写文本文件的效率,同时,提供了更方便的按行读取的方法:readLine();处理文本时,我们一般可以使用缓冲字符流。 -
字节数组流
ByteArrayInputStream和ByteArrayOutputStream经常用在需要流和数组之间转化的情况!说白了,FilelnputStream是把文件当做数据源。ByteArrayInputstream则是把内存中的”某个字节数组对象”当做数据源。 -
数据流
数据流将“基本数据类型与字符串类型”作为数据源,从而允许程序以与机器无关的方式从底层输入输出流中操作Java基本数据类型与字符串类型。
DatalnputStream和Data0utputStream提供了可以存取与机器无关的所有Java基础类型数据(如:int、double、String等)的方法。
DatalnputStream和Data0utputStream是处理流,可以对其他节点流或处理流进行包装,增加一些更灵活、更高效的功能。 -
对象流
ObjectInputStream/0bjectOutputStream是以“对象”为数据源,但是必须将传输的对象进行序列化与反序列化操作。需要序列化的对象,需要实现接口:java.io.Serializable对象序列化的作用有如下两种:
持久化:把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中,比如:休眠的实现。以后服务器session管理,hibernate将对象持久化实现。
网络通信:在网络上传送对象的字节序列。比如:服务器之间的数据通信、对象传递。
-
转换流
InputStreamReader/0utputStreamWriter用来实现将字节流转化成字符流。 -
随意访问文件流
RandomAccessFile可以实现两个作用:
1.实现对一个文件做读和写的操作。
2.可以访问文件的任意位置。不像其他流只能按照先后顺序读取。
4.装饰器模式构建IO流体系
- 装饰器模式简介
装饰器模式是GOF23种设计模式中较为常用的一种模式。它可以实现对原有类的包装和装饰,使新的类具有更强的功能。 - Apache IO包:功能强大,直接快速实现IO流。