概述
IO流是数据的流从源头流到目的地。流(Stream)是一组有顺序,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在俩设备之间的传输称为流,流的本质是数据传输。
分类
- 按照操作数据类型的不同分为两种:字节流和字符流。
字节流:字节流主要是操作byte类型数据。
字符流:因为数据编码的不同,而有了对字符进行高效操作的流对象,其本质就是基于字节流读取时,去查了指定的码表。
区别:
(1) 读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
(2)处理对象不同:字节流能处理所有类型的数据,字符流只能处理字符类型的数据。
(3)字节流操作的时候不会用到缓冲区,是对文件本身直接操作。而字符流在操作的时候会用到缓冲区,通过缓冲区操作文件。
- 流按照数据流向的不同分为:输出流和输入流。
输入流:从文件中读到程序中。
输入流:从程序中写到文件中。
这里输出流和输入流的参照物是程序
字节流
字节流基类
-
InputStream:是所有字节输入流的父类。首先看InputStream的定义:
public abstract class InputStream extends Object implements Closeable
可以看出它是一个抽象类,如果想要使用此类,首先必须通过子类实例化对象,如果要操作一个文件的话,则可以使用:FileInputStream类,通过向上转型之后,可以为InputStream实例化。
InputStream的常用方法:
//从输入流中读取数据的下一个字节
abstract int read()
// 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b中
int read(byte[] b)
// 将输入流中最多 len 个数据字节读入 byte 数组
int read(byte[] b, int off, int len)
// 关闭此输入流并释放与该流关联的所有系统资源
void close()
-
OutputStream:字节输出流的最大父类,OutputStream的定义:
public abstract class InputStream extends Object implements Closeable
它与InputStream一样,是个抽象类,必须依靠其子类来实例化。
OutputStream的常用方法:
//将b.length个字节从指定的byte数组写入此输出流
void write(byte[] e)
// 将指定的字节写入此输出流
abstract void write(int b)
// 关闭此输入流并释放与该流关联的所有系统资源
void close()
// 刷新此输出流并强制写出所有缓冲的输出字节
void flush()
字节文件操作流
- FileInputStream:字节文件输入流,从系统中的某个文件中获得输入字节,用于读取诸如图像数据之类的原始字节。
构造方法:
//通过打开到一个实际文件的连接来创造FileInputStream,该文件通过文件系统File对象file指定
FileInputStream(File file)
//通过打开到一个实际文件的连接来创造FileInputStream,该文件通过文件系统中路径name指定
FileInputStream(String name)
常用方法:覆盖和重写了父类的方法。
例子:
在f盘的hello文件下新建一个文本,内容为ABCD。
// 读取f盘下该文件f://hello/test.txt
//构造方法1
File file = new ("f://hello//test.txt");
InputStream inputStream = new FileInputStream(file);
int i = 0;
//一次读取一个字节
while((i=inputStream.read()) != -1){
//System.out.print(i +" ");//输出65 66 67 68
//为什么会输出65 66 67 68?因为字符在底层存储的时候就是存储的数值。即字符对应的ASCII码
System.out.print((char)i + " "); //输出A B C D
//关闭IO流
inputStream.close();
}
// 读取f盘下该文件f://hell/test.txt
//构造方法2
InputStream inputStream2 = new FileInputStream("f://hello/test.txt");
// 字节数组
byte[] b = new byte[2];
int i2 = 0;
// 一次读取一个字节数组
while ((i2 = inputStream2.read(b)) != -1) {
System.out.print(new String(b, 0, i2) + " ");// AB CD
}
//关闭IO流
inputStream2.close();
- FileOutputStream:字节文件输出流,用于将数据写入到File,从程序中写入到其他位置。
构造方法:
//创建一个向指定File对象表示的文件中写入数据的文件输出流
FileOutputStream(File file)
//创建一个向指定File对象表示的文件中写入数据的文件输出流
FileOutputStream(File file, boolean append)
//创建一个向具有指定名称的文件中写入数据的文件输出流
FileOutputStream(String name)
//创建一个向具体有指定name的文件写入数据的文件输出流
FileOutputStream(String name, boolean append)
有两个构造方法各多了一个boolean参数append。append参数为true时,数据从文件尾部写入;append参数为false时,数据覆盖原文件。
常用方法:覆盖和重写了父类的方法。
例子:
OutputStream outputStream = new FileOutputStream("d://test.txt");
//写出数据
outputStream.write("ABCD".getBytes());
//关闭IO流
outputStream.close();
//内容追加写入
OutputStream outputStream2 = new FileOutputStream("d://test.txt", true);
//输出换行符
outputStream2.write("\r\n".getBytes());
//输出追加内容
outputStream2.write("hello".getBytes());
//关闭IO流
ouputStream2.close();
注意:输出的目的地文件不存在,则会自动创建,不指定盘符的话,默认创建在项目目录下;输出换行符时一定要写\r\n不能只写\n,因为不同文本编辑器对换行符的识别存在差异性。
字节缓冲流
- BufferInputStream:字节缓冲输入流,提高了读写效率。
构造方法:
//创建一个BufferInputStream并保存参数,即输入流in,以便将来使用。
BufferInputStream(InputStream in)
// // 创建具有指定缓冲区大小的 BufferedInputStream并保存其参数,即输入流in以便将来使用
BufferInputStream(InputStream in, int size)
从构造方法中我们可以知道BufferedInputStream没有无参构造方法,它必须传入一个InputStream(一般是FileInputStream),来一起使用,以提高读写效率。
例子:
InputStream in = new FileInputStream("test.txt");
// 字节缓存流
BufferedInputStream bis = new BufferedInputStream(in);
byte[] bs = new byte[20];
int len = 0;
while ((len = bis.read(bs)) != -1) {
System.out.print(new String(bs, 0, len));
// ABCD
// hello
}
// 关闭流
bis.close();
- BufferOutputStream:字节缓冲输出流,提高了写出效率。
构造方法:
//创建一个新的缓冲输出流,将数据写入指定的底层输出流
BufferOutputStream(OutputStream out)
//创建一个新的缓冲输出流,将具有指定缓冲区大小的数据写入底层输出流
BufferOutputStream(OutputStream out, int size)
常用方法:
// 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此缓冲的输出流
void write(byte[] b, int off, int len)
// 将指定的字节写入此缓冲的输出流
void write(int b)
// 刷新此缓冲的输出流
void flush()
例子:
OutputStream outputStream = new FileOutputStream("test.txt",true);
BufferOutputStream bos = new BufferOutputStream(outputStream);
bos.write("\r\n".getBytes());
//输出内容
bos.write("hello word!".getBytes());
//刷新此缓冲的输出流
bos.flush();
//关闭流
bos.close();
字符流
字符流基类
- Reader:读取字符流的抽象类
常用方法:
//读取单个字符
int read()
//将字符读入数组
int read(char[] cbuf)
//将字符读入数组的某个部分
abstract int read(char[] cbuf, int off, int len)
//关闭该流并释放与之关联的所有资源
abstract void close()
- write:写入字符流的抽象类
常用方法:
// 写入字符数组
void write(char[] cbuf)
// 写入字符数组的某一部分
abstract void write(char[] cbuf, int off, int len)
// 写入单个字符
void write(int c)
// 写入字符串
void write(String str)
// 写入字符串的某一部分
void write(String str, int off, int len)
// 将指定字符添加到此 writer
Writer append(char c)
// 将指定字符序列添加到此 writer
Writer append(CharSequence csq)
// 将指定字符序列的子序列添加到此 writer.Appendable
Writer append(CharSequence csq, int start, int end)
// 关闭此流,但要先刷新它
abstract void close()
// 刷新该流的缓冲
abstract void flush()
字符转换流
- InputStreamReader:字节流转字符流,它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
- OutputStreamWrite:字节流转字符流。
字符缓冲流(高效流)
- BufferReader:字符缓冲流,从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
- BufferWrite:字符缓冲流,将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入