Java IO详解(五)------包装流
1.介绍
缓冲流:是一个包装流,目的是缓存作用,加快读取和写入数据的速度。
字节缓冲流:BufferedInputStream、BufferedOutputStream
字符缓冲流:BufferedReader、BufferedWriter
以介质是硬盘为例,字节流和字符流的弊端:
在每一次读写的时候,都会访问硬盘。 如果读写的频率比较高的时候,其性能表现不佳。
为了解决以上弊端,采用缓存流。
缓存流在读取的时候,会一次性读较多的数据到缓存中,以后每一次的读取,都是在缓存中访问,直到缓存中的数据读取完毕,再到硬盘中读取。
就好比吃饭,不用缓存就是每吃一口都到锅里去铲。用缓存就是先把饭盛到碗里,碗里的吃完了,再到锅里去铲缓存流在写入数据的时候,
会先把数据写入到缓存区,直到缓存区达到一定的量,才把这些数据,一起写入到硬盘中去。按照这种操作模式,就不会像字节流,字符流那样每写一个字节都访问硬盘,从而减少了IO操作。
2.我们查看 缓冲流的 JDK 底层源码,可以看到,程序中定义了这样的 缓存数组,大小为 8192
BufferedInputStream:
public class BufferedInputStream extends FilterInputStream { private static int DEFAULT_BUFFER_SIZE = 8192;
BufferedOutputStream:
public BufferedOutputStream(OutputStream out) { this(out, 8192); }
3.字节缓冲输入流、字节缓冲输出流
BufferedInputStream、BufferedOutputStream
package stream; import java.io.*; /*** * @ClassName: BufferedInputStreamDem * @Description: TODO * @Auther: chujiu * @Date: 2020/6/9 * @version : V1.0 */ public class BufferedInputStreamDem { public static void main(String[] args) throws IOException {
//字节缓冲输入流,创建文件字符流,缓存流必须建立在一个存在的流的基础上 BufferedInputStream bis = new BufferedInputStream( new FileInputStream("G:" + File.separator + "javabased" + File.separator + "JavaTest" + File.separator + "java.txt")); //定义一个字节数组,用来存储数据 byte[] buffer = new byte[1024]; int len = -1;//定义一个整数,表示读取的字节数 while ((len = bis.read(buffer)) != -1) { System.out.println(new String(buffer, 0, len)); } //关闭流资源 bis.close(); //字节缓冲输出流,创建文件字符流,缓存流必须建立在一个存在的流的基础上 BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream("G:" + File.separator + "javabased" + File.separator + "JavaTest" + File.separator + "java.txt")); bos.write("ABCD".getBytes()); //关闭流资源 bos.close(); } }
4.字符缓冲输入流、字符缓冲输出流
BufferedReader、BufferedWriter
package stream; import java.io.*; /*** * @ClassName: BufferedReaderDemo * @Description: TODO * @Auther: chujiu * @Date: 2020/6/9 * @version : V1.0 */ public class BufferedReaderDemo { public static void main(String[] args) throws IOException { //字符缓冲输入流,创建文件字符流,缓存流必须建立在一个存在的流的基础上 BufferedReader br = new BufferedReader( new FileReader("G:" + File.separator + "javabased" + File.separator + "JavaTest" + File.separator + "java.txt")); char[] buffer = new char[10]; int len = -1; while ((len = br.read(buffer)) != -1) { System.out.println(new String(buffer, 0, len)); } //关闭流资源 br.close(); //字符缓冲输出流,创建文件字符流,缓存流必须建立在一个存在的流的基础上 BufferedWriter bw = new BufferedWriter( new FileWriter("G:" + File.separator + "javabased" + File.separator + "JavaTest" + File.separator + "java.txt")); bw.write("ABCD"); //关闭流资源 bw.close(); } }
5.转换流:把字节流转换为字符流
InputStreamReader:把字节输入流转换为字符输入流
OutputStreamWriter:把字节输出流转换为字符输出流
用转换流进行文件的复制:
package stream; import java.io.*; /*** * @ClassName: FileOutputStreamCopy * @Description: TODO * @Auther: chujiu * @Date: 2020/6/10 * @version : V1.0 */ public class FileOutputStreamCopy { public static void main(String[] args) throws IOException { /** * 将 a.txt 文件 复制到 b.txt 中 */ //1、创建源和目标 File srcFile = new File("G:" + File.separator + "javabased" + File.separator + "JavaTest" + File.separator + "a.txt"); File descFile = new File("G:" + File.separator + "javabased" + File.separator + "JavaTest" + File.separator + "b.txt"); //2、创建字节输入输出流对象 InputStream in = new FileInputStream(srcFile); OutputStream out = new FileOutputStream(descFile); //3、创建转换输入输出对象 Reader rd = new InputStreamReader(in); Writer wt = new OutputStreamWriter(out); //3、读取和写入操作 char[] buffer = new char[10];//创建一个容量为 10 的字符数组,存储已经读取的数据 int len = -1;//表示已经读取了多少个字符,如果是 -1,表示已经读取到文件的末尾 while ((len = rd.read(buffer)) != -1) { wt.write(buffer, 0, len); } //4、关闭流资源 rd.close(); wt.close(); } }
6.内存流(数组流)
把数据先临时存在数组中,也就是内存中。所以关闭 内存流是无效的,关闭后还是可以调用这个类的方法。底层源码的 close()是一个空方法。
public void close() throws IOException { }
①、字节内存流:ByteArrayOutputStream 、ByteArrayInputStream
package stream2; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; /*** * @ClassName: ByteArrayDemo * @Description: TODO * @Auther: chujiu * @Date: 2020/6/10 2:51 * @version : V1.0 */ public class ByteArrayDemo { public static void main(String[] args) throws IOException { //字节数组输出流:程序---》内存 ByteArrayOutputStream bos = new ByteArrayOutputStream(); //将数据写入到内存中 bos.write("ABCD".getBytes()); //创建一个新分配的字节数组。 其大小是此输出流的当前大小,缓冲区的有效内容已被复制到其中。 byte[] temp = bos.toByteArray(); System.out.println(new String(temp, 0, temp.length)); byte[] buffer = new byte[10]; ///字节数组输入流:内存---》程序 ByteArrayInputStream bis = new ByteArrayInputStream(temp); int len = -1; while ((len = bis.read(buffer)) != -1) { System.out.println(new String(buffer, 0, len)); } //这里不写也没事,因为源码中的 close()是一个空的方法体 bos.close(); bis.close(); } }
②、字符内存流:CharArrayReader、CharArrayWriter
package stream2; import java.io.CharArrayReader; import java.io.CharArrayWriter; import java.io.IOException; /*** * @ClassName: CharArrayDemo * @Description: TODO * @Auther: chujiu * @Date: 2020/6/10 * @version : V1.0 */ public class CharArrayDemo { public static void main(String[] args) throws IOException { //字符数组输出流 CharArrayWriter caw = new CharArrayWriter(); caw.write("ABCD"); //返回内存数据的副本 char[] temp = caw.toCharArray(); System.out.println(new String(temp)); //字符数组输入流 CharArrayReader car = new CharArrayReader(temp); char[] buffer = new char[10]; int len = -1; while ((len = car.read(buffer)) != -1) { System.out.println(new String(buffer, 0, len)); } } }
③、字符串流:StringReader,StringWriter(把数据临时存储到字符串中)
package stream2; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; /*** * @ClassName: StringReaderDemo * @Description: TODO * @Auther: chujiu * @Date: 2020/6/10 * @version : V1.0 */ public class StringReaderDemo { public static void main(String[] args) throws IOException { //字符串输出流,底层采用 StringBuffer 进行拼接 StringWriter sw = new StringWriter(); sw.write("ABCD"); sw.write("帅锅"); System.out.println(sw.toString());//ABCD帅锅 //字符串输入流 StringReader sr = new StringReader(sw.toString()); char[] buffer = new char[10]; int len = -1; while ((len = sr.read(buffer)) != -1) { System.out.println(new String(buffer, 0, len));//ABCD帅锅 } } }
6.合并流:把多个输入流合并为一个流,也叫顺序流,因为在读取的时候是先读第一个,读完了在读下面一个流。
package stream2; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.SequenceInputStream; /*** * @ClassName: SequenceInputStreamDemo * @Description: TODO * @Auther: chujiu * @Date: 2020/6/10 * @version : V1.0 */ public class SequenceInputStreamDemo { public static void main(String[] args) throws IOException { //定义字节输入合并流 SequenceInputStream seinput = new SequenceInputStream( new FileInputStream("G:" + File.separator + "javabased" + File.separator + "JavaTest" + File.separator + "a.txt"), new FileInputStream("G:" + File.separator + "javabased" + File.separator + "JavaTest" + File.separator + "b.txt")); byte[] buffer = new byte[10]; int len = -1; while ((len = seinput.read(buffer)) != -1) { System.out.println(new String(buffer, 0, len)); } seinput.close(); } }
参考文章:https://www.cnblogs.com/ysocean/tag/Java%20IO%E8%AF%A6%E8%A7%A3%E7%B3%BB%E5%88%97/