JavaEE 初阶篇-深入了解 I O 高级流(缓冲流、交换流、数据流和序列化流)

5.2 对象字节输入流(ObjectInputStream 类)


1.0 缓冲流概述

缓冲流(Buffered Stream)来提高 I/O 操作的效率,缓冲流是对字节流和字符流的一种封装,通过缓冲区来减少 I/O 操作的次数,从而提高程序的运行效率。缓冲流的实现类有 BufferedInputStream、BufferedOutputStream、BufferedReader 和 BufferedWriter 。

1.1 缓冲流的工作原理

在读取数据时,缓冲流会将数据先读入缓冲区,等到缓冲区满或者达到一定条件时,再将缓冲区中的数据一次性写入到目标设备中;在写入数据时,缓冲流会将数据先写入缓冲区,等到缓冲区满或者达到一定条件时,再将缓冲区中的数据一次性写入到目标设备中。

1.2 使用缓冲流的步骤

1)创建字节流或者字符流对象。

2)将字节流或字符流对象作为参数创建缓冲流对象。

3)通过缓冲流对象进行数据读取获取写入操作

4)关闭缓冲流对象,同时会自动关闭底层的字节流或字符流对象。

1.3 字节缓冲流于字符缓冲流的区别

1)字节缓冲流会在内存中分配一个大小为 8 KB 的缓冲区来存储数据。这个缓冲区会在读取或写入数据时起到缓冲作用,减少对底层输入流或输出流的直接访问,提高读写效率。

2)字符缓冲流会在内存中分配 8K(8192)的字符缓冲池,可以提高字符输入流读取字符数据的性能。

3)字符缓冲流特有方法:

public String readLine() throws IOException:读取一行字符数据,以换行符为结束标志,返回读取的字符串(不包括换行符)。

public void newLine() throws IOException:写入一个换行符,根据系统的换行符规范来写入换行符。

1.4 字节缓冲流的实例

1)字节输出缓冲流来进行写文件操作

代码如下:

import java.io.*;

public class BufferedOut {
    public static void main(String[] args) throws IOException {
        OutputStream os = new FileOutputStream("D:\\software\\code\\2023_java\\2023_java_code\\code_24_25\\src\\MyIO\\Text.text");
        //将低级流转化为高级流
        BufferedOutputStream bos = new BufferedOutputStream(os);
        bos.write('a');
        bos.write('b');
        bos.write('c');
        bos.write('d');
        bos.write('f');
        bos.write('g');

        //关闭高级流,系统就会自动关闭低级流
        bos.close();
    }
}

运行结果:

2)字节输入缓冲流来进行读文件操作

代码如下:

import java.io.*;

public class BufferedIs {
    public static void main(String[] args) throws IOException {
        InputStream is = new FileInputStream("D:\\software\\code\\2023_java\\2023_java_code\\code_24_25\\src\\MyIO\\Text.text");
        //将低级流转化为高级流
        BufferedInputStream bis = new BufferedInputStream(is);
        int len;
        while ((len = bis.read()) != -1){
            System.out.print((char) len);
        }
    }
}

运行结果:

1.5 字符缓冲流的实例

1)字符输出缓冲流来进行写文件操作。

代码如下:

import java.io.*;

public class BufferedW {
    public static void main(String[] args) throws IOException {
        //先创建字符流(低级流)
        Writer writer = new FileWriter("D:\\software\\code\\2023_java\\2023_java_code\\code_24_25\\src\\MyIO\\Text.text");
        //将低级流转化为高级流
        BufferedWriter bw = new BufferedWriter(writer);
        //开始写文件操作
        bw.write("字符缓冲流内部的缓冲区大小通常是比较合适的,一般在 8 KB 到 16 KB 之间。");
        //刷新数据
        bw.flush();
        //换行操作
        bw.newLine();
        bw.write("这个大小是经过实际测试和性能优化的,能够在提高读写效率的同时,又不会占用过多的内存。");
        //操作完毕之后,需要关闭资源,关闭高级流,低级流也会自动关闭的。
        bw.close();
    }
}

运行结果:

2)字符输入缓冲流进行将文件的内容进行打印

代码如下:

import java.io.*;

public class BufferedR {
    public static void main(String[] args) throws IOException {
        Reader reader = new FileReader("D:\\software\\code\\2023_java\\2023_java_code\\code_24_25\\src\\MyIO\\Text.text");
        BufferedReader br = new BufferedReader(reader);

        //开始读文件操作
        String len;
        while ((len = br.readLine()) != null){
            System.out.println(len);
        }
        //结束程序需要关闭资源
        br.close();
    }
}

运行结果:

2.0 转换流概述

在 Java 中,字符流和字节流之间存在着转换的需求。字符流用于处理文本数据,而字节流用于处理二进制数据。转换流提供了 InputStreamReader 和 OutputStreamWriter 两个类,用于将字节流转换为字符流或将字符流转换为字节流。

InputStreamReader 类从字节流中读取数据,并根据指定的字符编码将字节数据转换为字符数据;OutputStreamWriter 类将字符数据按照指定的字符编码转换为字节数据并写入到字节流中。

转换流的主要作用包括:

1)字节流和字符流之间的转换:转换流可以方便地将字节流转换为字符流,或将字符流转换为字节流。

2)字符编码和解码:转换流可以指定字符编码,用于将字节数据转换为字符数据或将字符数据转换为字节数据。

3)处理文本数据:转换流通常用于处理文本数据,提供了更方便的字符操作方法。

2.1 字符输入转换流的实例( InputStreamReader 类)

简单来说,InputStreamReader 将读取的字节流转化为字符流,并且如果读取的是用 GBK 编码集进行编码的,在 UTF 环境下进行编码时,则需要指定用 GBK 编码集进行编码。

代码如下:

import java.io.*;

public class demo1 {
    public static void main(String[] args) throws FileNotFoundException {
        try(InputStream inputStream = new FileInputStream("D:\\software\\code\\2023_java\\2023_java_code\\code_24_4_26\\src\\ExchangeStreams\\Text");

            //将读取的文件字节流转化为字符流,并指定用GBK编码集进行编码
            Reader inputStreamReader = new InputStreamReader(inputStream,"GBK");
            //再将其转化为缓冲流
            BufferedReader br = new BufferedReader(inputStreamReader);
        ){
            String str;
            while ((str = br.readLine()) != null){
                System.out.println(str);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行结果:

2.2 字符输出转化流的实例(OutputStreamWriter 类)

简单来说,把原始的字节输出流,按照指定的字符集编码转换成字符输出转换流。就是将字节输出流转换为字符输出流,并且按指定的编码集编码输出。

代码如下:

import java.io.*;

public class demo2 {
    public static void main(String[] args) {
        try(OutputStream outputStream = new FileOutputStream("D:\\software\\code\\2023_java\\2023_java_code\\code_24_4_26\\src\\ExchangeStreams\\T");
            //将字节输出流转化为字符输出转换流
            Writer osw = new OutputStreamWriter(outputStream,"GBK");
            //再将字符输出转化流升级为缓冲流
            BufferedWriter bw = new BufferedWriter(osw);
        ) {
            bw.write("在这个美丽的世界里,每一天都是新的开始。阳光洒在大地上,微风拂过脸庞,让人感受到生命的美好。");
            bw.newLine();
            bw.write("无论遇到怎样的困难和挑战,我们都要勇敢面对,坚定前行。生活充满了无限可能,让我们抓住每一个机会,追逐自己的梦想。");
            bw.newLine();
            bw.write("愿每个人都能拥有快乐与幸福,享受生活的点滴美好。");
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

3.0 打印流概述

打印流 :PrintStream 和 PrintWriter 是 Java I/O 中的高级流,用于将各种数据类型格式化并输出到目标设备,如控制台、文件或网络连接。PrintStream 和 PrintWriter 提供了方便的方法来输出各种数据类型,包括基本数据类型、字符串、对象等。

简单来说:打印什么内容,就会输出什么内容。

3.1 字节打印流(PrintStream 类)

构造方法:

1)public PrintStream(OutputStream/File/String):打印流直接通向字节输出流/文件/文件路径。

2)public PrintStream(String fileName,Charset charset):可以指定写出去的字符编码。

3)public PrintStream(OutputStream out,boolean autoFlush):可以指定实现自动刷新。

4)public PrintStream(OutputStream out,boolean autoFlush,String encoding):可以指定实现自动刷新,并可指定字符的编码。

常用的方法:

1)public void println(xxx):打印任意类型的数据出去。

2)public void write(int / byte[] / byte[] 一部分):可以支持写字节数据出去。

代码演示:

import java.io.IOException;
import java.io.PrintStream;

public class MyPrintStream {
    public static void main(String[] args) {
        try(PrintStream printStream = new PrintStream("D:\\software\\code\\2023_java\\2023_java_code\\code_24_4_26\\src\\Print\\TT")
        ){
            //打印啥就会输出啥
            printStream.println(111);
            printStream.println( );
            printStream.println('A');
            printStream.println("你好世界");
            printStream.println("你好小鸭");
            printStream.println();
            printStream.println("你好小扳");

            //支持输出字节数据
            printStream.write(98);
            printStream.write('A');
            printStream.write("你好小狗".getBytes());

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

运行结果:

3.2 字符打印流(PrintWrite 类)

构造方法:

1)public PrintWrite(OutputStream/File/String/Write):打印流直接通向字节输出流/文件/文件路径/字符输出流。

2)public PrintWrite(String fileName,Charset charset):可以指定写出去的字符编码。

3)public PrintWrite(OutputStream out/Write,boolean autoFlush):可以指定实现自动刷新。

4)public PrintWrite(OutputStream out,boolean autoFlush,String encoding):可以指定实现自动刷新,并可指定字符的编码。

常用的方法:

1)public void println(xxx):打印任意类型的数据出去,打印什么就输出什么内容。

2)public void write(int/String/char[]/…):可以支持写字符数据出去。

代码演示:

import java.io.IOException;
import java.io.PrintWriter;

public class MyPrintWrite {
    public static void main(String[] args) {
        try(PrintWriter printWriter = new PrintWriter("D:\\software\\code\\2023_java\\2023_java_code\\code_24_4_26\\src\\Print\\TT")){
            printWriter.println(1);
            printWriter.println("你好鸭小鸭");
            printWriter.println("你好鸭小猫");
            printWriter.println("你好鸭小狗");
            printWriter.println();
            printWriter.println("A");
            printWriter.println('a');
            printWriter.println("你好鸭小板");

            //还支持字符输入流
            printWriter.write(98);
            printWriter.write("A");
            printWriter.write("你好鸭小童");
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

运行结果:

补充:如果需要追加数据,则需要用到低级流对象作为高级流的参数,低级流构造器中第二个参数 true 可以实现数据追加。

代码如下:

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class MyPrintWrite {
    public static void main(String[] args) {
        try(PrintWriter printWriter = new PrintWriter(new FileWriter("D:\\software\\code\\2023_java\\2023_java_code\\code_24_4_26\\src\\Print\\TT",true))){
            printWriter.println(1);
            printWriter.println("你好鸭小鸭");
            printWriter.println("你好鸭小猫");
            printWriter.println("你好鸭小狗");
            printWriter.println();
            printWriter.println("A");
            printWriter.println('a');
            printWriter.println("你好鸭小板");

            //还支持字符输入流
            printWriter.write(98);
            printWriter.write("A");
            printWriter.write("你好鸭小童");
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

运行结果:

4.0 数据流概述

数据流是 Java I/O 中的一种特殊流,用于读取或写入原始数据类型(如 int、double、char 等)而不是字节或字符。数据流提供了方便的方法来读取和写入基本数据类型,避免了手动进行数据类型转换的繁琐工作。

在 Java 中,数据流主要包括 DataInputStream 和 DataOutputStream。它们分别是字节数据流和字符数据流的装饰器,可以包装其他输入流或输出流,以便读取或写入基本数据类型。

适用于网络通信和文件操作:数据流常用于网络通信和文件操作中,方便地读取和写入基本数据类型。

4.1 数据输出流(DataOutputStream 类)

构造方法:

public DataOutputStream(OutputStream out):创建新数据输出包装基础的字节输出流。

常用的方法:

1)public final void writeByte(byte v):将 byte 类型的数据写入基础的字节输出流。

2)public final void writeInt(int v):将 int 类型的数据写入基础的字节输出流。

3)public final void writeDouble(Double v):将 double 类型的数据写入基础的字节输出流。

4)public final void writeUTF(String str):将字符串数据以 UTF-8 编码成字节写入基础的字节输出流。

5)public void write(int/byte[]/byte[] 一部分):支持写字节数据出去。

代码演示:

import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class MyDataInOutStream {
    public static void main(String[] args) {
        //先创建低级输出流
        try(OutputStream os = new FileOutputStream("D:\\software\\code\\2023_java\\2023_java_code\\code_24_4_26\\src\\Data\\DataText");
            //再继续转化为高级流
            DataOutputStream dos = new DataOutputStream(os);
        ){
            dos.writeByte(1);
            dos.writeInt(333);
            dos.writeDouble(333.01);
            dos.writeUTF("你好鸭小蜜蜂!!!!");
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

运行结果:

需要注意的是:这是正常的情况而不是乱码,这是一个特殊的存储方法,可以理解为将类型和内容进行了“打包”。主要是为了,方便取数据而不是给程序员看的。

4.2 数据输入流(DataInputStream 类)

用于读取数据输出流写出去的数据。注意读取的顺序应该跟写数据的顺序保持一致。

构造方法:

public DataInputStream(InputStream is):创建新数据输入流包装基础的字节输入流。

常用的方法:

1)public final byte readByte():读取字节数据返回。

2)public final int readInt():读取 int 类型的数据返回。

3)public final double readDouble():读取 double 类型的数据返回。

4)public final String readUTF():读取字符串(UTF-8)数据返回。

5)public int read(byte[]):支持字节数据进来。

代码演示:

import java.io.*;

public class MyDataInputStream {
    public static void main(String[] args) {
        try(InputStream inputStream = new FileInputStream("D:\\software\\code\\2023_java\\2023_java_code\\code_24_4_26\\src\\Data\\DataText");
            DataInputStream dis = new DataInputStream(inputStream);
        ){
            byte b = dis.readByte();
            System.out.println(b);
            int i = dis.readInt();
            System.out.println(i);
            double dl = dis.readDouble();
            System.out.println(dl);
            String str = dis.readUTF();
            System.out.println(str);
        }catch (IOException e){
            e.printStackTrace();
        }
    }

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

img

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

ntStackTrace();

    }
}

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

[外链图片转存中…(img-wDcBtFT2-1715491747260)]

[外链图片转存中…(img-DQaGapi3-1715491747261)]

[外链图片转存中…(img-YISj3wy9-1715491747261)]

[外链图片转存中…(img-j9gaG1kq-1715491747261)]

[外链图片转存中…(img-2Hp9MDGn-1715491747261)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值