IO中节点流和处理流的理解学习

1. 流的分类

  • 按数据流的方向不同:

    • 输入流
    • 输出流。
  • 按处理数据单位不同:

    • 字节流

      数据流中最小的数据单元是字节

    • 字符流

      数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节

  • 按功能不同:

    • 节点流

      程序用于直接操作目标设备所对应的类叫节点流

    • 处理流

      程序通过一个间接流类去调用节点流类,以达到更加灵活方便地读写各种类型的数据,这个间接流类就是处理流

2. 节点流

2.1 节点流的类型

这里写图片描述

  • **File 文件流:**对文件进行读、写操作 :FileReader、FileWriter、FileInputStream、FileOutputStream。、
  • Memory
    1. 从/向内存数组读写数据: CharArrayReader与 CharArrayWriter、ByteArrayInputStream与ByteArrayOutputStream。
    2. 从/向内存字符串读写数据 StringReader、StringWriter、StringBufferInputStream。
  • Pipe管道流: 实现管道的输入和输出(进程间通信): PipedReader与PipedWriter、PipedInputStream与PipedOutputStream。

2.2 节点流执行的图示

这里写图片描述

3. 处理流

3.1 处理流的类型

这里写图片描述

  • **Buffering缓冲流:**在读入或写出时,对数据进行缓存,以减少I/O的次数:BufferedReader与BufferedWriter、BufferedInputStream与BufferedOutputStream。
  • **Filtering 滤流:**在数据进行读或写时进行过滤:FilterReader与FilterWriter、FilterInputStream与FilterOutputStream。
  • **Converting between Bytes and Characters 转换流:**按照一定的编码/解码标准将字节流转换为字符流,或进行反向转换(Stream到Reader):InputStreamReader、OutputStreamWriter。
  • **Object Serialization 对象流 :**ObjectInputStream、ObjectOutputStream。
  • DataConversion数据流: 按基本数据类型读、写(处理的数据是Java的基本类型(如布尔型,字节,整数和浮点数)):DataInputStream、DataOutputStream 。
  • Counting计数流: 在读入数据时对行记数 :LineNumberReader、LineNumberInputStream。
  • Peeking Ahead预读流: 通过缓存机制,进行预读 :PushbackReader、PushbackInputStream。
  • Printing打印流: 包含方便的打印方法 :PrintWriter、PrintStream。

3.2 处理流执行的图示

这里写图片描述

3.3 缓冲流

  • 对I/O进行缓冲是一种常见的性能优化,缓冲流为I/O流增加了内存缓冲区,增加缓冲区的两个目的:
    1. 允许Java的I/O一次不只操作一个字符,这样提高䇖整个系统的性能;
    2. 由于有缓冲区,使得在流上执行skip、mark和reset方法都成为可能。
  • 缓冲流:它是要“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能,
    提高了读写的效率,同时增加了一些新的方法。例如:BufferedReader中的readLine方法,
    BufferedWriter中的newLine方法。
  • J2SDK提供了4种缓存流,常用的构造方法为:
//字符输入流
BufferedReader(Reader in)//创建一个32字节的缓冲区
BufferedReader(Reader in, int size)//size为自定义缓存区的大小

//字符输出流
BufferedWriter(Writer out)
BufferedWriter(Writer out, int size)

//字节输入流
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in, int size)

//字节输出流
BufferedOutputStream(OutputStream in)
BufferedOutputStream(OutputStream in, int size)
  • 其他
    (1)缓冲输入流BufferedInputSTream除了支持read和skip方法之外,还支持其父类的mark和reset方法;
    (2)BufferedReader提供了一种新的ReadLine方法用于读取一行字符串(以\r或\n分隔);
    (3)BufferedWriter提供了一种新的newLine方法用于写入一个行分隔符;
    (4)对于输出的缓冲流,BufferedWriter和BufferedOutputStream,写出的数据会先在内存中缓存,
    使用flush方法将会使内存的数据立刻写出。
  • 示例1:
import java.io.*;
public class TestBufferStream1 {
  public static void main(String[] args) {
    try {
      FileInputStream fis = new FileInputStream(
		  "d:\\JavaProject\\demo13\\ProcessingStream\\TestBufferStream1.java");
      BufferedInputStream bis = new BufferedInputStream(fis);
      int c = 0;
      System.out.println((char)bis.read());
      System.out.println((char)bis.read());
      bis.mark(100);/*在当前输入流的当前位置上做一个标志,允许最多再读入100个字节*/
      for(int i=0;i<=10 && (c=bis.read())!=-1;i++){
        System.out.print((char)c+" ");
      }
      System.out.println(); 
      bis.reset();/*把输入指针返回到以前所做的标志处*/
      for(int i=0;i<=10 && (c=bis.read())!=-1;i++){
        System.out.print((char)c+" ");
      }
      bis.close();
    } catch (IOException e) {e.printStackTrace();}
  }
}
  • 示例2:
import java.io.*;
public class TestBufferStream2
{
	public static void main(String[] args)
	{
	try{
	BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\JavaProject\\demo13\\BufferStream\\dat2.txt"));
	BufferedReader br = new BufferedReader(new FileReader("D:\\JavaProject\\demo13\\BufferStream\\dat2.txt"));
	String s = null;
	for(int i=0;i<10;i++)
	{
		s = String.valueOf(Math.random());//产生一个小于1的正的随机数,并转换成字符串形式
		bw.write(s);//把字符串s写入到dat2.txt文件中
		bw.newLine();//写入一个行分隔符
	}
	bw.flush();//使用flush方法将会使内存的数据立刻写出

	while((s=br.readLine()) != null)
	{
		System.out.println(s);
	}
	bw.close();
	br.close();
	}
	catch(IOException e)
	{
		e.printStackTrace();
	}

	}
}

四个缓冲流简单使用

BufferedReader
/**
 * @author:雷子杰
 * @date:2022/7/26
 */
public class BufferedReader_ {
    public static void main(String[] args) {
        String filePath="f:\\b.txt";
        FileReader fileReader = null;
        BufferedReader bufferedReader = null;
        try {
            fileReader = new FileReader(filePath);
            bufferedReader = new BufferedReader(fileReader,8);

            String line;

            while ((line = bufferedReader.readLine())!=null){
                System.out.println(line);
            }


        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                //底层是关闭我们传入的fileReader的流
                bufferedReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }
}
BufferedWriter
/**
 * @author:雷子杰
 * @date:2022/7/26
 */
public class BufferedWriter_ {
    public static void main(String[] args) throws IOException {

        String filePath = "f:\\ok.txt";

        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));
        bufferedWriter.write("哈哈哈哈哈哈哈哈哈哈哈");
        bufferedWriter.newLine();
        bufferedWriter.write("qqqqqqqq啊");

        bufferedWriter.close();

    }
}
BufferedInputStream和BufferedOutputStream
/**
 * @author:雷子杰
 * @date:2022/7/26
 */
public class BufferedCopy02_ {
    public static void main(String[] args) {

        String srcFilePath = "f:\\ssm博客系统.jpg";
        String filePath = "e:\\ssm博客系统.jpg";

        BufferedInputStream bufferedInputStream = null;
        BufferedOutputStream bufferedOutputStream = null;

        byte[] buff = new byte[1024];
        int readLength;

        try {
            bufferedInputStream = new BufferedInputStream(new FileInputStream(srcFilePath));
            bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(filePath));

            while ((readLength = bufferedInputStream.read(buff))!=-1){
                bufferedOutputStream.write(buff,0,readLength);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {

                try {
                    if (bufferedOutputStream!=null){
                    bufferedOutputStream.close();
                    }
                    if (bufferedInputStream!=null){
                        bufferedInputStream.close();
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }
}

3.4 转换流

转换流有两种:

  1. InputStreamReader:将字节流转换为字符流;
  2. OutputStreamWriter:将字符流转换为字节流。
  3. 在使用时可以指定编码格式(utf-8\gbk\gb2312\ISO8859-1等)

**介绍:**主要用于文件中出现乱码的情况

  1. 文件内容输入的时候使用字节流进行读取处理(可以指定编码格式),读取到程序中后转换使用字符流进行读取处理显示
  2. 在写入文件时,使用字符流的方式写入内容到文件,但是内容的传递方式是使用字节流的方式,并可以指定内容编码格式
  • 什么时候使用转换流?由以下分析: 流对象很多,就要明确使用哪个流对象。
通过三点来完成: 
	1、明确数据的来源和数据到达的目的地。
	             来源:输入流 [InputStream,Reader]。 
	             目的:输出流 [OutputStream,Writer]。 
	2、操作的数据是否是纯文本。  
	             是:字符流,使用Reader与Writer; 
	             否:字节流,使用InputStream与OutputStream。 
	3、明确要使用哪个具体的对象。 通过设备来进行区分: 
	             源设备:内存用数组,硬盘就加file,键盘用System.in; 
	             目的设备:内存用数组,硬盘就加file,键盘用System.out。 
	4、明确是否还需要其他额外功能:例如 
	            (1)是否需要较高的效率,即是否需要使用缓冲区,是就加上Buffered;
	            (2)是否需要转换,是,就使用转换流,InputStreamReader 和 OutputStreamWriter。
  • 用一个例子简单的说明: 将键盘录入的数据保存到一个文件中,输入“over”时表示录入结束。 详细分析:
源:从InputStream,Reader中选择; 因为是键盘录入的是纯文本,所以使用Reader。 
设备:键盘,所以用System.in; 发现System.in是字节流的操作,与Reader(字符流)矛盾,
这时就要用到转换流 InputStreamReader 。为了提高操作效率,使用缓冲技术,选择BufferedReader。 

目的:从 OutputStream,Writer中选择。 因为是文本文件,所以选择Writer。 
设备:硬盘上,一个文件,选择FileWriter。 为了提高操作效率,使用缓冲技术,选择BufferedWriter。 

InputStreamReader

将字节流转换为字符流

使用代码示例:

文件内容输入的时候使用字节流进行读取处理(可以指定编码格式),读取到程序中后转换使用字符流进行读取处理显示

/**
 * @author:雷子杰
 * @date:2022/7/26
 */
public class InputStreamReader_ {
    public static void main(String[] args) throws IOException {
        String filePath = "f:\\b.txt";

        //将 FileInputStream 转成 InputStreamReader
        //指定gbk编码读取
        InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(filePath), "gbk");

        //把InputStreamReader传入 BufferedReader
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

        //读取
        String line;

        while ((line = bufferedReader.readLine())!=null){
            System.out.println(line);
        }

        bufferedReader.close();

    }
}

OutputStreamWriter

将字符流转换为字节流

使用代码示例:

在写入文件时,使用字符流的方式写入内容到文件,但是内容的传递方式是使用字节流的方式,并可以指定内容编码格式

/**
 *
 * 字节流转换成字符流
 *
 * @author:雷子杰
 * @date:2022/7/26
 */
public class OutputStreamWriter_ {
    public static void main(String[] args) throws IOException {
        String filePath="f:a.txt";

        //传入字节流对象,指定编码格式为utf-8
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(filePath), "utf-8");

        //使用字符流的方式写入
        outputStreamWriter.write("lzj");
        outputStreamWriter.close();
        System.out.println("文件保存类型为utf-8类型");


    }
}

3.5 对象流

**对象流:**ObjectOutputStream和ObjectInputStream

**介绍:**使用对象流,可以将值和数据类型保存到文件中,在需要时可以将其完整取出

注意:

  1. 如果对象流中传递的是我们自己声明的对象,则该对象必须实现Serializable接口
  2. 在读取文件中的内容(反序列化)时,顺序需要和保存数据的顺序一致,否则会异常

ObjectOutputStream

ObjectOutputStream的使用示例代码:

/**
 * @author:雷子杰
 * @date:2022/7/26
 */
public class ObjectOutStream_ {


    public static void main(String[] args) throws IOException {
        ObjectOutputStream objectOutputStream = null;
        ObjectInputStream
        //学历恶化后,保存的文件格式不是存文本,而是按照他的格式存储
        String filePath = "f:\\data.dat";

        objectOutputStream = new ObjectOutputStream(new FileOutputStream(filePath));

        //序列化数据到f:\data.dat
        objectOutputStream.writeInt(100);//int -> integer
        objectOutputStream.writeBoolean(true);//boolean -> Boolean
        objectOutputStream.writeChar('a');//char -> Character
        objectOutputStream.writeDouble(9.5);//double -> Double
        objectOutputStream.writeUTF("lzj");//String
        //保存一个Dog对象
        objectOutputStream.writeObject(new Dog("旺财",10));
        //关闭流
        objectOutputStream.close();
    }
}

class Dog implements Serializable {
    private String name;
    private int age;

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

生成的文件内容:

image-20220726165813080

ObjectInputStream

ObjectInputStream的使用示例代码:

/**
 * @author:雷子杰
 * @date:2022/7/26
 */
public class ObjectInputStream_ {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //指定反序列化的文件
        String filePath = "f:\\data.dat";

        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filePath));

        //读取反序列化的顺序需要和保存数据的顺序一致,否则会异常
        System.out.println(objectInputStream.readInt());
        System.out.println(objectInputStream.readBoolean());
        System.out.println(objectInputStream.readChar());
        System.out.println(objectInputStream.readDouble());
        System.out.println(objectInputStream.readUTF());
        Object dog = objectInputStream.readObject();
        //这里输出类的运行类型
        System.out.println(dog.getClass());
        //这里是正常获得类
        System.out.println(dog);

        //如果我们希望调用Dog的方法,则我们需要将dog对象向下转型为Dog类
        //Dog dog1 = (Dog) dog;

        //关闭外层流即可
        objectInputStream.close();

    }
}

输出结果:

image-20220726165707845

3.6 数据流——数据的存储和数据恢复

  • 数据流:DataInputStream和DataOutputStream

    1. DataInputStream和DataOutputStream是面向字节的,因此要使用InputStream和OutputStream。

    2. DataInputStream和DataOutputStream分别继承InputStream和OutputStream,

    3. 它们属于处理流,需要分别“套接”在InputStream和OutputStream类型的节点流上。

    4. DataInputStream和DataOutputStream提供了可以存取与机器无关的Java原始类数据(如:int,double等)的方法。

    5. DataInputStream和DataOutputStream的构造方法:

       DataInputStreamInputStream in)
       DataOutputStreamOutputStream out)
      
  • 示例1:

import java.io.*;
public class TestDataStream
{
	public static void main(String[] args) throws IOException
	{
		FileOutputStream fout = new FileOutputStream("D:/JavaProject/demo13_IO/DataStream/demo.txt",true);
	    BufferedOutputStream bout = new BufferedOutputStream(fout);
	    DataOutputStream dout = new DataOutputStream(bout);
		/*DataOutputStream,BufferedOutputStream,FileOutputStream这里使用了流栈。*/

	    dout.writeInt(110);
	    dout.writeUTF("hello,中国");
	    dout.writeFloat(3.14f);
	    dout.writeChar(97);/*97对应的是'a'*/
        dout.close();/*如果正在使用一个流栈,程序关闭最上面的一个流也就自动的关闭了栈中的所有底层流。*/
		
		FileInputStream fin = new FileInputStream("D:/JavaProject/demo13_IO/DataStream/demo.txt");
		BufferedInputStream bin = new BufferedInputStream(fin);
		DataInputStream din = new DataInputStream(bin);
		
		int i = din.readInt();
		String str = din.readUTF();
		float f = din.readFloat();
		char c = din.readChar();
		fin.close();/*如果正在使用一个流栈,程序关闭最上面的一个流也就自动的关闭了栈中的所有底层流。*/
        System.out.println("int:"+i+"\nString:"+str+"\nfloat:"+f+"\nchar:"+c);
	}
	
}
  • 编译,运行:
D:\JavaProject\demo13_IO\DataStream>javac TestDataStream.java

D:\JavaProject\demo13_IO\DataStream>java TestDataStream
int:110
String:hello,中国
float:3.14
char:a
  • 注意:
        int i = din.readInt();
		String str = din.readUTF();
		float f = din.readFloat();
		char c = din.readChar();
		/*此段代码的顺序不能乱,要保证先写入的先读出来的原则,否则会出现错误。
		*    因此,我们在写代码的时候,我们必须:
		*         要么为文件中的数据采用固定的格式;
		*         要么将额外的信息保存到文件中,以便能够对其进行解析以确定数据的寻访位置。
		*/

3.7 打印流

打印流包括以下两个类:PrintStream、PrintWriter

注意:打印流只有输出流,没有输入流

PrintStream

字节打印流

  1. 我们在java中使用的输出就是使用的字节打印流
  2. 我们可以更改字节打印流输出的位置
/**
 * 
 * 字节打印流
 * 
 * @author:雷子杰
 * @date:2022/7/26
 */
public class PrintStream_ {
    public static void main(String[] args) throws IOException {
        PrintStream out = System.out;
        //默认情况下,PrintStream输出数据的位置是标准输出,即显示器
        out.print("hello,world");

        //因为print底层使用的是write()方法,所以我们可以直接调用该方法进行打印输出
        out.write("hello,lzj".getBytes());

        out.close();

        //我们可以修改打印流输出的位置/设备
        //将语句输出到f:\f1.txt
        System.setOut(new PrintStream("f:\\f1.txt"));
        System.out.println("hello,lzj哈哈哈");
    }
}

PrintWriter

字符打印流

/**
 * 
 * 字符打印流
 * 
 * @author:雷子杰
 * @date:2022/7/26
 */
public class PrintWriter_ {
    public static void main(String[] args) throws IOException {
        //输出到java的客户端
        //PrintWriter printWriter = new PrintWriter(System.out);

        //输出到f:\f2.txt
        PrintWriter printWriter = new PrintWriter(new FileWriter("f:\\f2.txt"));

        printWriter.print("hi,武汉你好");
        printWriter.close();
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱学习的大雄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值