一、字节输入流InputStream 和 字节输出流outputStream
ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三种基本的介质流,它们分别从Byte 数组、StringBuffer、和本地文件中读取数据。PipedInputStream 是从与其它线程共用的管道中读取数据,与Piped 相关的知识后续单独介绍。
ObjectInputStream 和所有FilterInputStream的子类都是装饰流(装饰器模式的主角)。意思是FileInputStream类可以通过一个String路径名创建一个对象,FileInputStream(String name)。而DataInputStream必须装饰一个类才能返回一个对象,DataInputStream(InputStream in)。
ByteArrayOutputStream、FileOutputStream是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。PipedOutputStream 是向与其它线程共用的管道中写入数据,
ObjectOutputStream 和所有FilterOutputStream的子类都是装饰流。具体例子跟InputStream是对应的。
1、FileInputStream
通过打开与实际文件的连接创建一个 |
|
通过打开与实际文件的连接来创建一个 |
2、FileInputStream
创建文件输出流以写入由指定的 |
创建文件输出流以写入由指定的 |
|
创建文件输出流以指定的名称写入文件。 |
创建文件输出流以指定的名称写入文件。 |
(1)、读文件内容
public class FileInputStreamTest {
public static void main(String[] args) throws IOException {
FileInputStream fin = new FileInputStream("src\\IOTest\\testfile.txt");
byte[] b=new byte[1024];
//一次从该输入流读取最多 b.length个字节的数据
fin.read(b);
fin.close();
System.out.println(new String(b));
}
}
(2)、写内容进文件
public class OutputStreamTest {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("src\\IOTest\\write.txt");
String str="Hello IOStream";
byte[] b=str.getBytes();
//将 b.length个字节从指定的字节数组写入此文件输出流。
fos.write(b);
fos.close();
}
}
如果文件不存在,则创建一个;如果文件存在,则覆盖其中的所有内容。
想要在存在的文件中追加内容:FileOutputStream fos = new FileOutputStream("src\\IOTest\\write.txt",true);会把新的内容直接加在后面。
(3)复制文件内容
public class CopyFileTest {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("src\\IOTest\\testfile.txt");
FileOutputStream fos = new FileOutputStream("src\\IOTest\\copy.txt");
// 创建一个1M大小的缓冲区,用来存放输入流中的字节
byte[] buff = new byte[1024 * 1024];
// 用来保存实际读到的字节数
int len = 0;
while ((len = fis.read(buff)) != -1) {
fos.write(buff, 0, len);
}
fis.close();
fos.close();
}
}
二、缓冲流-BufferedInputStream、BufferedOutputStream
1、简介:
BufferedInputStream
和BufferedOutputStream
这两个类分别是FilterInputStream
和FilterOutputStream
的子类,作为装饰器子类,使用它们可以防止每次读取/发送数据时进行实际的写操作,代表着使用缓冲区。
(1)不带缓冲:每读一个字节就要写入一个字节,由于涉及磁盘的IO操作相比内存的操作要慢很多,所以不带缓冲的流效率很低。
(2)带缓冲的流:一次可以读很多字节,但不向磁盘中写入,只是先放到内存里。等凑够了缓冲区大小的时候一次性写入磁盘,这种方式可以减少磁盘操作次数,速度就会提高很多!BufferedInputStream
和BufferedOutputStream
类就是实现了缓冲功能的输入流/输出流。使用带缓冲的输入输出流,效率更高,速度更快。
注意:BufferedOutputStream
写完数据后,要调用flush()
方法或close()
方法,强行将缓冲区中的数据写出。
2、总结:
BufferedInputStream
是缓冲输入流。它继承于FilterInputStream
。BufferedInputStream
的作用是为另一个输入流添加一些功能,例如,提供“缓冲功能”以及支持mark()标记
和reset()重置方法
。BufferedInputStream
本质上是通过一个内部缓冲区数组实现的。例如,在新建某输入流对应的BufferedInputStream
后,当我们通过read()
读取输入流的数据时,BufferedInputStream
会将该输入流的数据分批的填入到缓冲区中。每当缓冲区中的数据被读完之后,输入流会再次填充数据缓冲区;如此反复,直到我们读完输入流数据位置。
3、看看构造方法以及常用方法:
(1)BufferedInputStream
//创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
//创建一个内部缓冲区数组并将其存储在 buf 中,该buf的大小默认为8192。
public BufferedInputStream(InputStream in);
//创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
//创建一个长度为 size 的内部缓冲区数组并将其存储在 buf 中。
public BufferedInputStream(InputStream in,int size);
从构造方法中我们可以知道BufferedInputStream没有无参构造方法,它必须传入一个InputStream(一般是FileInputStream),来一起使用,以提高读写效率。
常用方法:
//从该输入流中读取一个字节
public int read();
//从此字节输入流中给定偏移量处开始将各字节读取到指定的 byte 数组中。
public int read(byte[] b,int off,int len);
(2)BufferedOutputStream
//使用默认大小、底层字节输出流构造bos。默认缓冲大小是 8192 字节( 8KB )
//创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
public BufferedOutputStream(OutputStream out);
//创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。
public BufferedOutputStream(OutputStream out,int size);
常用方法:
//向输出流中输出一个字节
public void write(int b);
//将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此缓冲的输出流。
public void write(byte[] b,int off,int len);
//刷新此缓冲的输出流。这迫使所有缓冲的输出字节被写出到底层输出流中。
public void flush();
4、复制文件:
public class BufferedTest {
public static void main(String[] args) throws IOException {
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream("src\\IOTest\\testfile.txt"));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("src\\IOTest\\bufferedCopy.txt"));
byte[] buffer = new byte[1024*1024];
int len = 0;
while((len=bis.read(buffer))!=-1) {
bos.write(buffer, 0, len);
}
//刷新输出流,保证数据全部写出到文件中
bos.flush();
bis.close();
bos.close();
}
}
查看BufferedOutputStream的源代码,发现所谓的buffer其实就是一个byte[]。BufferedOutputStream的每一次write其实是将内容写入byte[],当buffer容量到达上限时,会触发真正的磁盘写入。而另一种触发磁盘写入的办法就是调用flush()了。