走近Java之IO流(二)
  BA7aR24amlGh 2023年11月05日 56 0

走近Java之IO流(二)_处理流

节点流和处理流

基本介绍

  1. 节点流可以从一个特定的数据源读写数据,如FileReader、FileWriter
  2. 处理流(也叫包装流)是“连接” 在已经存在的流(节点流或处理流)之上,为程序提供更强大的读写功能,也更加灵活,如BufferedReader、BufferedWriter。

节点流和处理流一览表

分类

字节输入流

字节输出流

字符输入流

字符输出流

抽象基类

InputStream

OutputStream

Reader

Writer

访问文件

FileInputStream

FileOutputStream

FileReader

FileWriter

访问数组

ByteArrayInputStream

ByteArrayOutputStream

CharArrayReader

CharArrayWriter

访问管道

PipedInputStream

PipedOutputStream

PipedReader

PipedWriter

访问字符串

StringReader

StringWriter

缓冲流

BufferedInputStream

BufferedOutputStream

BufferedReader

BufferedWriter

转换流

InputStreamReader

OutputStreamWriter

对象流

ObjectInputStream

ObjectOutputStream

抽象基类

FilterInputStream

FilterOutputStream

FilterReader

Filter

打印流

PrintStream

PrintWriter

推回输入流

PushbackInputStream

PushbackReader

特殊流

DataInputStream

DataOutputStream

注:红色为字节流,紫色为处理流

节点流和处理流的区别和联系

  1. 节点流是底层流/低级流,直接跟数据源相接。
  2. 处理流(包装类)包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出。
  3. 处理流(也叫包装流)对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连

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

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

处理流-BufferedReader和BufferedWriter

走近Java之IO流(二)_处理流_02

在源码中,BufferedReader类中,有属性Reader,即可以封装一个节点流,该节点流可以是任意的,只要是Reader子类都可(FileReader、CharArrayReader、PipedReader等等,只要是Reader的子类就可以,但是一次只能放一个),这也说明包装流更加强大。通过传入的Reader(子类)来决定访问文件/数组/管道。

 BufferedWriter原理同上:

走近Java之IO流(二)_处理流_03

代码模拟:

package com.study.srv.demo17;

/**
 * @author Wen先森
 * @version 1.0
 * @date 2022/6/29 10:37
 * 模拟流
 */
public class Demo09 {
    public static void main(String[] args) {
        BuffReader buffReader = new BuffReader(new FileReader());
        buffReader.reader();
        buffReader.fileReader(4);

        BuffReader buffReader1 = new BuffReader(new ArrayReader());
        buffReader1.fileReader(3);

        BuffReader buffReader2 = new BuffReader(new PipeReader());
        buffReader2.fileReader(2);

    }


}

abstract class AbstractReader {
    public void printf() {
    }
    //抽象方法可以用空方法体,也可以用abstract
    //public abstract void printf();
}


/**
 * 模拟节点流
 */
class FileReader extends AbstractReader {
    @Override
    public void printf() {
        System.out.println("对文件进行打印");
    }
}


/**
 * 模拟节点流
 */
class ArrayReader extends AbstractReader {
    @Override
    public void printf() {
        System.out.println("对数组进行打印");
    }
}


/**
 * 模拟节点流
 */
class PipeReader extends AbstractReader {
    @Override
    public void printf() {
        System.out.println("对管道进行打印");
    }
}

/**
 * 模拟包装流/处理流
 */
class BuffReader extends AbstractReader {
    /**
     * 属性是AbstractReader类型
     */
    private AbstractReader in;

    /**
     * 接受AbstractReader子类对象
     *
     */
    public BuffReader(AbstractReader in) {
        this.in = in;
    }

    /**
     * 封装一层方法
     */
    public void reader() {
        in.printf();
    }

    /**
     * 多次调用
     *
     */
    public void fileReader(int num) {
        for (int i = 0; i < num; i++) {
            in.printf();
        }
    }
}

走近Java之IO流(二)_System_04

BufferedReader和BufferedWriter属于字符流,是按照字符来读取数据,关闭时处理流,只需要关闭外层流即可。

因为在使用包装流,就是通过外层的包装流最终调用了内层包装的节点流,所以在关闭处理流/包装流的时候,底层会自动关闭内层包装的节点流。

BufferedReader示例:

package com.study.srv.demo17;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

/**
 * @author Wen先森
 * @version 1.0
 * @date 2022/6/29 15:53
 */
public class Demo10 {
    public static void main(String[] args) throws IOException {
        //读取文件路径
        String src="E:\\c.txt";
        //创建包装流BufferedReader对象
        BufferedReader bufferedReader = new BufferedReader(new FileReader(src));
        String line;
        //bufferedReader.readLine())是按行读取,
        //通过下列字符之一即认为某行已终止:换行 ('\n')、回车 ('\r') 或回车后直接跟着换行。
        //包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
        while ((line=bufferedReader.readLine())!=null){
            System.out.println(line);
        }
        //关闭外层包装/处理流,就会自动关闭内部的节点流
        bufferedReader.close();
    }
}

走近Java之IO流(二)_java_05

BufferedWriter示例:

package com.study.srv.demo17;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

/**
 * @author Wen先森
 * @version 1.0
 * @date 2022/6/29 16:23
 * 演示BufferedWriter使用
 */
public class Demo11 {
    public static void main(String[] args) throws IOException {
        //文件地址,有则直接写入,无则先创建文件再进行写入
        String src="E:\\test.txt";
        //创建一个处理流BufferedWriter对象,并且设置节点流默认拼接写入
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(src,true));
        bufferedWriter.write("这是一条测试");
        //换行,写入一个行分隔符。行分隔符字符串由系统属性 line.separator 定义,
        // 并且不一定是单个新行 ('\n') 符。 
        bufferedWriter.newLine();
        bufferedWriter.write("这是一条新的测试数据2");
        //同样写入完毕后,关闭包装流/处理流。
        bufferedWriter.close();
    }
}

走近Java之IO流(二)_处理流_06

文件拷贝:

package com.study.srv.demo17;

import java.io.*;
import java.io.FileReader;

/**
 * @author Wen先森
 * @version 1.0
 * @date 2022/6/29 17:10
 * 利用包装流实现文件拷贝
 */
public class Demo12 {
    public static void main(String[] args) {
        //所选复制文件地址
        String src="E:\\c.txt";
        //所选复制后文件地址
        String path="E:\\copy.txt";
        BufferedReader bufferedReader=null;
        BufferedWriter bufferedWriter = null;
        String line;

        try {
            //创建处理流/包装流,BufferedReader和BufferedWriter对象
            //值得注意的是BufferedReader和BufferedWriter是字符处理流
            //不能去操作二进制文件,会造成文件损坏
            bufferedReader = new BufferedReader(new FileReader(src));
            bufferedWriter = new BufferedWriter(new FileWriter(path));
            //一行一行读取
            while ((line=bufferedReader.readLine())!=null){
                //一行一行写入
                bufferedWriter.write(line);
                //换行
                bufferedWriter.newLine();
            }
            System.out.println("文件拷贝完毕");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭包装流
            try {
                if (bufferedReader!=null) {
                    bufferedReader.close();
                }
                if (bufferedWriter!=null) {
                    bufferedWriter.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

走近Java之IO流(二)_处理流_07

处理流-BufferedInputStream 和 BufferedOutputStream

BufferedInputStream是字节流,在创建BufferInputStream时,会创建一个内部缓冲区数组。

package com.study.srv.demo17;

import java.io.*;

/**
 * @author Wen先森
 * @version 1.0
 * @date 2022/6/30 11:48
 * 使用BufferedInputStream和BufferedOutputStream拷贝文件
 * 完成二进制文件拷贝
 */
public class Demo13 {
    public static void main(String[] args) {
        //复制对象地址
        String pathA = "E:\\c.txt";
        //复制后地址
        String pathB = "E:\\x.txt";
        //创建BufferedInputStream和BufferedOutputStream对象
        BufferedInputStream bufferedInputStream = null;
        BufferedOutputStream bufferedOutputStream = null;

        byte[] bytes = new byte[1024];
        int length;
        try {
            //FileInputStream是InputStream子类
            bufferedInputStream = new BufferedInputStream(new FileInputStream(pathA));
            bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(pathB));
            //循环读取文件,被写入到复制文件中去。
            //如果到达流末尾,则返回 -1。
            while ((length = bufferedInputStream.read(bytes)) != -1) {
                //将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此缓冲的输出流。
                bufferedOutputStream.write(bytes, 0, length);
            }
            System.out.println("拷贝完毕");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bufferedInputStream != null) {
                    bufferedInputStream.close();
                }
                if (bufferedOutputStream != null) {
                    bufferedOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

走近Java之IO流(二)_java_08

 值得注意的是,字节流可以操作二进制文件(字节),也可以操作字符文件(因为字节是基本单位)。但是字符流不能操作二进制文件。


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
BA7aR24amlGh