JAVA IO流
一、相关概念
I/O流: Input/Output Stream,文件输入输出流。
1、分类:
-
输入流 和 输出流:(站在程序的角度) 根据读写操作/数据流动的方向区分。
- 其中输入流就是指读取文件中的内容输入到程序中的流,也就是读文件。
- 其中输出流就是指将程序中的内容输出到文件中的流,也就是写文件。
-
字节流 和 字符流:根据读写操作的基本单位分。
- 参考: https://blog.csdn.net/yogima/article/details/78705411
- 其中字节流就是指以字节为基本单位进行读写的流,可以处理任何文件。字节(8位 )
- 字符流就是指以字符(2个字节)为基本单位进行读写的流,只能处理文本文件。字符(16位)。Reader和Writer
-
数据传输方式:
- 节点流(Node Stream 直接和文件打交道)
- 包装流(又称处理流、过滤流、缓冲流)程序和文件之间有管道,不直接接触。
-
缓冲流:
- 什么是缓冲流:参考 https://www.cnblogs.com/aademeng/articles/10880511.html
- 意义:在内存与硬盘之间创建一个大小合适的缓冲区,当内存和硬盘进行数据访问时,能提高访问硬盘的次数,提高效率。
- 是一个包装流,目的起缓冲作用.包括:
- BufferedInputStream:字节输入缓冲流
- BufferedOutputStream:字节输出缓冲流
- BufferedReader:字符输入缓冲流
- BufferedWriter::字符输出缓冲流
区别和联系
1、节点流和处理流
-
(1)节点流是低级流,直接跟数据源相接。
- 处理流(也叫包装流)把节点流包装了一层,属于修饰器设计模式,不会直接与数据源相连,通过处理流来包装节点流既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出。
-
(2)处理流的功能主要体现在以下两个方面:
- 1.性能的提高:主要以增加缓冲的方式来提高输入输出的效率。
- 2.操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的内容,而不是输入/输出一个或多个水滴处理流可以嫁接在任何已存在的流的基础上。
-
节点流(Node Stream) :直接与原始数据存在的特定介质(如磁盘文件或其他外部设备、内存某区域或其他程序)打交道的流,在流的序列中离程序最远。
-
过滤流 (Filter Stream):使用其它的流作为输入源或输出目的地,对流中的数据提供进一步处理的流。其他的流可以是节点流,也可以是另一种过滤流。过滤流不能单独使用。
-
一个输入流链或输出流链中一定有且只有一个节点流;可以没有,也可以有多个过滤流。
2、字符流和字节流
代码
- 1、字节流: InputStream和OutputStream
- InputStream
InputStream是抽象类,不能直接用new InputStream()构造实例。 FileInputStream是InputStream的子类,可以生成实例。 FileInputStream有三个构造方法,最常用的构造方法如下: Public FileInputStream(String fileName) throws FileNotFoundException Public FileInputStream(File file) throws FileNotFoundException //fileName用来指定输入文件名及其路径,file是一个File对象 InputStream类的read()方法:逐字节以二进制的原始方式读取数据 public int read();//读入一个字节,-1表示无 public int read(byte b[]);//返回读入的字节数 public int read(byte[] b,int off.int len);//返回从某个位置开始制定长度的字节数
- OutputStream
构造方法: OutputStream是抽象类,不能直接用new OutputStream()构造实例。 FileOutputStream是OutputStream的子类,可以生成实例。 FileOutputStream最常用的构造方法如下: Public FileOutputStream(String name) throws FileNotFoundException Public FileOutputStream(String name,boolean append) throws FileNotFoundException //Name用来指定输入文件名及其路径,append为true时数据将添加到文件已有内容的末尾 常用方法: //写一个字节 void write( int ) throws IOException //关闭输出流 void close( ) throws IOException //强行将缓冲区的数据写到目的地。 void flush( ) throws IOException //写一个字节数组 void write(byte[ ] b) throws IOException void write(byte[ ] b, int offset, int length ) throws IOException
- InputStream
- 利用字节流复制文件
import java.io.*;
class CopyAFile
{
public static void main(String[] args)
{
InputStream in;
OutputStream out;
try
{
in=new FileInputStream("test.txt");
out=new FileOutputStream("copyResult.txt");
// out=new FileOutputStream("copyResult.txt",true);
int aByte;
aByte=in.read();
while (aByte!=-1)
{
out.write(aByte);
aByte=in.read();
}
in.close();
out.close();
System.out.println("文件复制完毕。test.txt已经复制到copyResult.txt中。");
}
catch(FileNotFoundException e)
{
System.out.println("当前目录下文件test.txt不存在!");
}
catch(IOException e)
{
System.out.println("发生输入输出错误!");
}
}
}
-
2、字符流: Reader和Writer
- 字符(16位)流不一定对应两个字节,要考虑到编码问题。
- 只能操作文本文件。
Reader类读取的是字符,而不是字节。 Reader类的重要方法read(): public int read();//需要将int转为char public int read(char b[]); public int read(char[] b,int off,int len)
-
3、滤流和节点流的套接:
InputStream in;
in=new BufferedInputStream(new FileInputStream("test.txt"));
BufferedReader in = new BufferedReader(new FileReader(file));
BufferedReader in2 = new BufferedReader(new inputStreamReader(new FileInputStream(file),"utf-8"));
s = in2.readLine();
嵌套的IO流关闭的问题
参考:https://blog.csdn.net/menghuanzhiming/article/details/77945822
- 当然完全可以只关闭处理流,不用关闭节点流。处理流关闭的时候,会调用其处理的节点流的关闭方法
一般情况下是:
- 先打开的后关闭,后打开的先关闭;
- 另一种情况:看依赖关系,如果流a依赖流b,应该先关闭流a,再关闭流b
- 例如处理流a依赖节点流b,应该先关闭处理流a,再关闭节点流b
- 如果将节点流关闭以后再关闭处理流,会抛出IO异常;