你需要知道的JavaI/O流(二)

57 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情

节点流和处理流

分类字节输入流字节输出流字符输入流字符输出流
抽象基类InputStreamOutputSrreamReaderWriter
访问文件FileInputStreamFileOutputStreamFileReaderFileWriter
访问数组ByteArrayInputStreamByteArrayOutputStreamCharArrayReaderCharArrayWriter
访问管道PipedInputStreamPipedOutputStreamPipedReaderPipedWriter
访问字符串StringReaderstringWriter
缓冲流BufferedInputStreamBufferedOutputStreamBufferedReadcrBufferedWriter
转换流InputStreamReaderOutputStreamWriter
对象流ObjectInputStreamObjectOutputStream
抽象基类FilterlnputStreamFilterOuputStreamFilterReaderFilterWriter
打印流PrintStreamPrintWriter
推回数入流PushbackInputStreamPushbackReader
特殊流DataInputStreamDataOutputStream

PS:加粗的几类为节点流,下面的为处理流或包装流

  1. 节点流可以从一个特定的数据源读写数据,如FileReader、FileWriter。
  2. 处理流(也叫包装流)是“连接”在已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,如BufferedReader、BufferedWriter。以BufferedReader为例,在这个类里面有个属性in为Reader类型,也就是说在使用BufferedReader是,可以将in构造为其他节点流来进行数据源的操作,功能更强大更灵活。(这种思想就是修饰器模式)

1.1 节点流和处理流的区别

1.节点流是底层流/低级流,直接跟数据源相接。

2.处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出。

3.处理流(也叫包装流)对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连。

处理流的功能主要体现在以下两个方面:

  1. 性能的提高:主要以增加缓冲的方式来提高输入输出的效率。
  2. 操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便

1.2 BufferedReader和BufferedWriter的使用

这两个处理流(BufferedWriter|BufferedReader)都使用对应的父类类型的子类进行构造对象(Writer和Reader都是抽象类不能实例化),这样就可以使用不同的子类对不同的数据源进行操作。常用的方法就是读/写操作以及关闭操作,对读写有不同的重载适合不同的场景,但是这两个包装流不适合操作二进制的文件(图片、音频、视频、pdf、word等文件),可能或造成文件损坏。

@Test
    public void testCopy() {
        String src = "E:\\MakeDir.java";
        String dest = "E:\\copy.java";
        BufferedReader bufferedReader = null;
        BufferedWriter bufferedWriter = null;
        try {
            bufferedReader = new BufferedReader(new FileReader(src));
            bufferedWriter = new BufferedWriter(new FileWriter(dest));
            String read;
            while ((read = bufferedReader.readLine()) != null){
                bufferedWriter.write(read);
                bufferedWriter.newLine();
            }
            System.out.println("复制完成");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bufferedReader!=null){
                    //实际上是对包装流包装的节点流进行关闭
                    bufferedReader.close();
                }
                if (bufferedWriter != null){
                    bufferedWriter.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

1.3 BufferedInputStream和BufferedOutputStream的使用

image.png image.png BufferedInputStreamBufferedOutputStream与前两个字符缓冲流类似,分别继承了FilterInputStream和FilterOutputStream,所以他们也有in/out属性,可以根据多态动态的传入需要的字节流进行处理,字节流不仅可以处理二进制文件,也可以处理文本文件,但是如果想把文本文件的内容输出到控制台或者直接处理还是建议用对应的字符流,不认很容易出现乱码。个人学习这两个类主要是对Api的学习以及运用,可以适当的看看源码,搞清楚不同类之间的关系,以及方法之间的调用关系。

@Test
public void testBufferInOutStream() throws IOException {
    String src = "E:\The xx - Intro.mp3";
    String dest = "E:\dest.mp3";
    BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(src));
    BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(dest));
    byte[] buff = new byte[1024];
    int readLen;
    while((readLen = bufferedInputStream.read(buff))!= -1){
        bufferedOutputStream.write(buff,0,readLen);
    }
    if (bufferedInputStream!=null){
        bufferedInputStream.close();
    }
    if (bufferedOutputStream!=null){
        bufferedOutputStream.close();
    }
}