常见流对象的使用

news2024/11/15 13:31:04

在这里插入图片描述

文章目录

  • 一、缓冲流
    • 字节缓冲流
    • 字符缓冲流
  • 二、转换流
    • 字符输入转换流
    • 字符输出转换流
  • 三、对象序列化
    • 对象序列化
    • 对象反序列化
  • 四、打印流
    • PrintStream
    • PrintWriter

一、缓冲流

缓冲流:也叫高效流或者高级流,我们之前学的字节流称为原始流,缓冲流自带缓冲区,可以提高原始字节流、字符流读写数据的性能。
原始流:
在这里插入图片描述
缓冲流
在这里插入图片描述

在这里插入图片描述

字节缓冲流

在这里插入图片描述
我们可以发现我们的缓冲流BufferedInputStream继承于InputStream.

字节缓冲流性能优化原理:
字节缓冲输入流自带8KB缓冲池,我们直接从缓冲池读取数据,所以性能较好。
字节缓冲输出流自带8KB缓冲池,数据就直接写入到缓冲池中去,写数据性能极高。

方法作用
BufferedInputStream(InputStream is)可以把一个低级的字节输入流包装成一个高级的缓冲字节输入流管道,从而提高字节输入流读数据的性能
BufferedOutputStream(OutputStream os)可以把一个低级的字节输出流包装成一个高级的缓冲字节输出流,从而提高写数据的性能

在这里插入图片描述
我们查一下缓冲字节输入流的构造方法
在这里插入图片描述
我们点进构造方法可以看到第二个参数传了一个8192的缓冲池大小的参数。
在这里插入图片描述
我们可以看到创建了一个8KB的字节数组,我们之前一个字节一个字节的读,现在直接一次性加载8KB的数据。
我们再来看一下缓冲字节输出流的构造方法
在这里插入图片描述
在这里插入图片描述
为什么我们会说缓冲字节输出流效率极高,因为我们直接的原始流是将内存的数据一个字节一个字节写到硬盘上,写到硬盘上的操作是比较慢的,而我们的缓冲字节输出流,是有一个8KB的缓冲池,这个缓冲池是内存的,我们内存写内存的操作是极快的。

我们这里的缓冲流的方法和原始流的方法基本是一致的,我们在这里就不详细介绍了。
我们分别使用初始字节流和缓冲字节流拷贝文件,比较一下性能。
在这里插入图片描述
分别使用四种方法:
1.使用初级的字节流按照一个字节一个字节的形式复制文件
2.使用初级的字节流按照一个一个字节数组的形式复制文件
3.使用缓冲字节流按照一个字节一个字节的形式复制文件
4.使用缓冲字节流按照一个一个字节数组的形式复制文件

public class Test {
    private static final String SRC_FILE = "D:\\workspace\\work.docx";//源文件路径
    private static final String DEST_FILE = "D:\\workspace1\\";//目的文件路径
    public static void main(String[] args) throws IOException {
        copy1();//使用初级的字节流按照一个字节一个字节的形式复制文件
        copy2();//使用初级的字节流按照一个一个字节数组的形式复制文件
        copy3();//使用缓冲字节流按照一个字节一个字节的形式复制文件
        copy4();//使用缓冲字节流按照一个一个字节数组的形式复制文件
    }

    private static void copy1() throws IOException {
        long startTime = System.currentTimeMillis();
        try(
                //1.创建初级的字节输入流与源文件接通
                InputStream inputStream = new FileInputStream(SRC_FILE);
                //2.创建低级的字节输出流与目标文件接通
                OutputStream outputStream = new FileOutputStream(DEST_FILE + "work1.docx");//动态定义目标文件名称
                ) {
            int len;
            while((len = inputStream.read()) != -1) {
                outputStream.write(len);
            }
        }catch (IOException e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("初级字节流一个一个字节花费: " +(endTime - startTime) + "时间" );
    }

    private static void copy2() {
        long startTime = System.currentTimeMillis();
        try(
                //1.创建初级的字节输入流与源文件接通
                InputStream inputStream = new FileInputStream(SRC_FILE);
                //2.创建低级的字节输出流与目标文件接通
                OutputStream outputStream = new FileOutputStream(DEST_FILE + "work2.docx");//动态定义目标文件名称
        ) {
            byte[] buffer = new byte[1024];
            int len;
            while ((len = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer,0,len);
            }
        }catch (IOException e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("初级字节流一个一个字节数组花费: " +(endTime - startTime) + "时间" );
    }


    private static void copy3() {
        long startTime = System.currentTimeMillis();
        try(
                //1.创建初级的字节输入流与源文件接通
                InputStream inputStream = new FileInputStream(SRC_FILE);
                //a.把原始的字节输入流包装成高级的缓冲字节输入流
                InputStream bis = new BufferedInputStream(inputStream);
                //2.创建低级的字节输出流与目标文件接通
                OutputStream outputStream = new FileOutputStream(DEST_FILE + "work3.docx");//动态定义目标文件名称
                //b.把字节输出流管道包装成高级的缓冲字节输出流
                OutputStream bos = new BufferedOutputStream(outputStream);
        ) {
            int len;
            while((len = bis.read()) != -1) {
                bos.write(len);
            }
        }catch (IOException e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("缓冲字节流一个一个字节花费: " +(endTime - startTime) + "时间" );
    }


    private static void copy4() {
        long startTime = System.currentTimeMillis();
        try(
                //1.创建初级的字节输入流与源文件接通
                InputStream inputStream = new FileInputStream(SRC_FILE);
                //a.把原始的字节输入流包装成高级的缓冲字节输入流
                InputStream bis = new BufferedInputStream(inputStream);
                //2.创建低级的字节输出流与目标文件接通
                OutputStream outputStream = new FileOutputStream(DEST_FILE + "work3.docx");//动态定义目标文件名称
                //b.把字节输出流管道包装成高级的缓冲字节输出流
                OutputStream bos = new BufferedOutputStream(outputStream);
        ) {
            byte[] buffer = new byte[1024];
            int len;
            while ((len = bis.read(buffer)) != -1) {
                bos.write(buffer,0,len);
            }
        }catch (IOException e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("缓冲字节流一个一个字节数组花费: " +(endTime - startTime) + "时间" );
    }
}

在这里插入图片描述
我们首先可以看到使用初级流,一个字节一个字节去操作,真的慢的要死,相比直接我们的缓冲字节流按照字节数组的方式读写是最快的。

字符缓冲流

字符缓冲输入流:BufferedReader,提高字符输入流读取数据的性能,除此之外多了按照行读取数据的功能。

方法作用
BufferedReader(Reader r)把初级的字符输入流包装成一个缓冲字符输入流
readLine()读取一行数据返回,如果读取没有完毕,无行可读返回null

在这里插入图片描述
我们先准备一个出师表的文件,之前按照一个字符一个字符读和一个字符数组的读我们这里就不介绍了。

public static void main(String[] args) {
        try(
                //创建一个字符输入流与源文件接通
                Reader reader = new FileReader("./data.txt");
                //把初级的字符输入流包装成缓冲字符输入流
                BufferedReader br = new BufferedReader(reader);
                ) {
            //使用一次读一行的方式读文件
            String line;
            while((line = br.readLine()) != null) {
                System.out.println(line);
            }
        }catch (IOException e) {
            e.printStackTrace();
        }
    }

在这里插入图片描述
字符缓冲输出流:BufferedWriter,提高字符输出流写数据的性能,除此之外多了换行功能。

方法作用
BufferedWriter(Writer w)把初级的字符输出流包装成一个缓冲字符输出流
newLine()换行操作

在这里插入图片描述
在这里插入图片描述
这里也是带了一个8KB的缓冲区。
在这里插入图片描述
这是我们写数据大概的一个顺序。

public static void main(String[] args) throws IOException {
        //创建一个字符输出流管道与源文件接通
        Writer writer = new FileWriter("./data.txt");
        BufferedWriter bw = new BufferedWriter(writer);

        //使用newLine实现换行功能
        bw.write("我是中国人");
        bw.newLine();
        bw.write("Chine");
        bw.newLine();
        bw.write("哈哈");
        bw.close();
    }

在这里插入图片描述

二、转换流

之前我们在使用字符流读取中文的时候是没有乱码的,因为我们代码的解码和文件编码的方式都是UTF-8。
但是如果代码和文件编码不一致,使用字符流直接读取就会出现乱码情况。
在这里插入图片描述
我们在这里准备一个GBK编码的文件。

public static void main(String[] args) {
        try(
                //文件为 GBK 代码UTF-8
                //创建一个字符输入流与源文件接通
                Reader reader = new FileReader("D:/workspace/data.txt");
                //把初级的字符输入流包装成缓冲字符输入流
                BufferedReader br = new BufferedReader(reader);
        ) {
            //使用一次读一行的方式读文件
            String line;
            while((line = br.readLine()) != null) {
                System.out.println(line);
            }
        }catch (IOException e) {
            e.printStackTrace();
        }
    }

在这里插入图片描述
我们会发现中文会出现乱码。

字符输入转换流

字符输入转换流:提取文件(GBK)的原始字节流,原始字节流是不存在问题的,然后把字节流以指定编码转换成字符输入流,这样字符输入流中的字符就不会出现乱码了。
在这里插入图片描述

方法作用
InputStreamReader(InputStream is)可以把原始的字节流按照代码默认编码转换成字符输入流
InputStreamReader(InputStream is,String charset)把原始的字节流按照指定编码转换成字符输入流

在这里插入图片描述

public static void main(String[] args) throws IOException {
        //文件GBK 代码UTF-8
        //提取文件的原始字节流
        InputStream is = new FileInputStream("D:/workspace/data.txt");
        //原始字节流转换成字符输入流
        Reader isr = new InputStreamReader(is,"GBK");//以GBK的方式转换为字符输入流
        BufferedReader br = new BufferedReader(isr);
        String line;
        while((line = br.readLine()) != null) {
            System.out.println(line);
        }
        br.close();
    }

在这里插入图片描述

字符输出转换流

如何控制写出去字符使用的编码?

  1. 可以把字符以指定的编码获取字节后在使用字节输出流写出去,“我是中国人”.getBytes(编码)
  2. 使用字符输出转换流
方法作用
OutputStreamWriter(OutputStream(os)将初级的字节输出流转换为代码默认字符的字符输出流
OutputStreamWriter(OutputStream os,String charset)将原始字节输出流转换为指定字符的字符输出流
public static void main(String[] args) throws IOException{
        //定义一个字节输出流
        OutputStream outputStream = new FileOutputStream("D:/workspace/data.txt");
        //将字节输出流转换为字符输出流
        Writer writer = new OutputStreamWriter(outputStream,"GBK");
        BufferedWriter bw = new BufferedWriter(writer);
        bw.write("我在试转换字符输出流");
        bw.newLine();
        bw.write("成功了吗?");
        bw.newLine();
        bw.write("成功了");
        bw.close();
    }

在这里插入图片描述

三、对象序列化

对象序列化

对象序列化:使用对象字节输出流(ObjectOutputStream)以内存为基准,把内存的对象存储到磁盘文件中,称为对象序列化
在这里插入图片描述
在这里插入图片描述
这是API文档为我们介绍的对象序列化的使用方式,我们来具体学习一下。

方法作用
ObjectOutputStream(OutputStream out)将初级字节输出流包装成高级的对象字节输出流
writeObject(Object obj)将对象写道对象序列化流的文件中去

在这里插入图片描述
在这里我们准备了一个Student类。

public static void main(String[] args) throws IOException {
        //创建一个学生对象
        Student student = new Student("张三",18,001);

        //对象序列化,使用对象字节输出流包装字节输出流管道
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("./data.txt"));

        //调用序列化方法
        oos.writeObject(student);

        oos.close();
    }

在这里插入图片描述
这里报了一个不可序列化异常,原因很简单因为我们的对象没有实现序列化接口,我们的对象要存到硬盘要遵守一定的规则,那么这个规则由谁来制定,肯定是由我们的java来制定。
在这里插入图片描述
在这里插入图片描述
看到这里,我们就序列化成功了,这里不是乱码,只供系统能够看懂。

对象反序列化

对象字节输入流(ObjectInputStream):将硬盘中的对象数据按照字节流到内存中的java对象
在这里插入图片描述

方法作用
ObjectInputStream(InputStream out)将低级的字节流输入流包装成对象字节输入流
readObject()将存储到磁盘文件中的对象数据恢复到内存中的对象返回
public static void main(String[] args) throws IOException, ClassNotFoundException {
        //创建对象字节输入流管道包装初级的字节输入流管道
        ObjectInputStream is = new ObjectInputStream(new FileInputStream("./data.txt"));

        Student stu = (Student)is.readObject();
        System.out.println(stu);
    }

在这里插入图片描述
我们在有些序列化的时候并不想将某些对象的部分信息序列化。
在这里插入图片描述
在这里插入图片描述
我们在进行序列化反序列化,我们transient修饰的变量是默认值。
我们一般也会申明序列化的版本号,只有我们的序列化和反序列化的版本号一致才不会出错,避免我们在反序列化之前对对象的一些属性进行了修改。
在这里插入图片描述
在这里插入图片描述
当我们在序列化版本号为1时序列化,序列化版本号为2时反序列化就会报一个无效类的异常,提醒我们重新序列化然后再进行反序列化。

四、打印流

打印流可以实现更方便,高效的打印数据到文件中去

PrintStream

方法作用
PrintStream(OutputStream os)打印流直接通向字节输出流管道
PrintStream(File f)打印流通向文件对象
PrintStream(String filepath)打印流通向文件路径
print(Xxx xxx)打印任意类型的数据
public static void main(String[] args) throws FileNotFoundException {
        PrintStream ps = new PrintStream("./data.txt");
        ps.println(1);
        ps.println(true);
        ps.println(10.5);
        ps.println("helloworld!");
        ps.close();
    }

在这里插入图片描述
在这里插入图片描述

加粗样式
我们可以顺着构造方法看些源码,是有包装缓冲字符输出流的,所以效率是比较高的。

PrintWriter

方法作用
PrintWriter(OutputStream os)打印流通向字节输出流管道
PrintWriter(Writer w)打印流通向字符输出流管道
PrintWriter(File f)打印流通向文件对象
PrintWriter(String filepath)打印流通向文件路径
print(Xxx xxx)打印任意类型数据

我们PrintWriter 和 PrintStream打印数据的方式是一样的,我们就不过多介绍了。
PrintWriter 和 PrintStream的区别
1.打印数据功能一模一样,使用方便,性能高效
2.PrintStream继承字节输出流OutputStream,支持写字节数据的方法
3.PrintWriter继承字符输出流Writer,支持写字符数据的方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/175711.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JavaSE】浅析String与StringTable

文章目录1. 前言2. String的两种创建方式2.1 通过new关键字创建一个字符串对象2.2 采用双引号的方式来创建字符串对象2.3 两种方式的区别3. StringTable的位置4. String的intern()方法5. 判断两个字符串是否相等5.1 equals5.2 1. 前言 String类是开发中经常使用的一个类。 对…

第七层:多态

文章目录前情回顾多态多态的基本概念动态多态的满足条件动态多态的使用虚函数多态的优点纯虚函数和抽象类抽象类特点虚析构和纯虚析构虚析构和纯虚析构的共性虚析构和纯虚析构的区别面向对象结束,接下来是什么?本章知识点(图片形式)&#x1…

数据结构进阶 哈希桶

作者:小萌新 专栏:数据结构进阶 作者简介:大二学生 希望能和大家一起进步! 本篇博客简介:模拟实现高阶数据结构 哈希桶 哈希桶哈希冲突的另一种解决方法开散列 -- 链地址法举例哈希表的开散列实现 --哈希桶哈希表的结构…

自动化测试Selenium【基础篇二】

自动化测试Selenium【基础篇二】🍎一.Selenium基础使用🍒1.1 信息打印🍉 1.1.1打印标题🍉 1.1.1打印当前网页标题🍒1.2 窗口🍉1.2.1 获取句柄🍉1.2.2 窗口切换🍉1.2.3 窗口大小设置&…

当你点击浏览器的瞬间都发生了什么----- 网络学习笔记

计算机网络前言web 浏览器协议栈创建套接字阶段。连接阶段。断开阶段。IP模块网卡网络设备 --- 集线器、交换器和路由器集线器交换器路由器路由器的附加功能一 :地址转换路由器的附加功能一 :包过滤功能互联网内部接入网光纤接入网(FTTH&…

JDK8 前后的 Date 日期时间 API

JDK8 前后的 Date 日期时间 API 每博一文案 师父说:人只要活在世界上,就会有很多的烦恼,痛苦或是快乐,取决于逆的内心,只要心里拥有温暖灿烂的阳光, 那么悲伤又有什么好畏惧的呢? 人生如行路&a…

vue学习笔记(更新中)

目录 简介 使用Vue写一个"hello,world" 前置准备 代码书写 MVVM模型理解 插值语法和指令语法 插值语法 指令语法 指令:v-bind 指令:v-model vue中的el和data的两种写法 数据代理 方法:defineProperty() 说明…

新年礼物已收到!2022 Apache IoTDB Commits 数量排名 3/364!

社区喜报!据 The Apache Software Foundation 官方 Projects Statistics(项目信息统计网站)的实时数据显示,Apache IoTDB 在过去 12 个月(即 2022 年度)共发表 6829 Commits,排名 2022 年度 Apa…

2、Three.js开发入门与调试设置

一、添加坐标轴辅助器 AxesHelper 用于简单模拟3个坐标轴的对象. 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴. 构造函数 AxesHelper( size : Number ) size -- (可选的) 表示代表轴的线段长度. 默认为 1. //添加坐标轴 const axesHelper new THREE.AxesHelper(5); sc…

CSS 特效之心形-彩虹-加载动画

CSS 特效之心形-彩虹-加载动画参考描述效果HTMLCSS重置元素的部分默认样式bodyli动画定义指定animationul抖动代码总汇参考 项目描述搜索引擎BingMDNMDN Web Docs 描述 项目描述Edge109.0.1518.61 (正式版本) (64 位) 效果 HTML <!DOCTYPE html> <html lang"e…

Keil C51工程转VSCode Keil Assistant开发全过程

Keil C51工程转VSCode Keil Assistant开发全过程✨这里以stc15W408AS为例。&#x1f4cc;相关篇《【开源分享】自制STC15W408AS开发板》 &#x1f4fa;编译-烧录演示&#xff1a; &#x1f4cb;转VSCODE开发环境主要原因可能代码提示以及代码跳转功能&#xff0c;或者其他。 &…

在java中操作redis

在普通项目中操作redis 1.导入maven坐标 <dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.8.0</version> </dependency>2.打开redis 如果redis-server闪退&#xff0c;那就先打开re…

【Spring Security】如何使用Lambda DSL配置Spring Security

本期目录1. 概述2. 新老配置风格对比Lambda风格等效的旧配置风格3. WebFlux Security4. Lambda DSL的目标1. 概述 在 Spring Security 5.2 中增强了 DSL 的功能&#xff1a;允许使用 Lambda 表达式来配置 HTTP security 。 需要注意的是&#xff1a;先前版本的配置风格仍然是…

二分查找——“C”

各位CSDN的uu们你们好呀&#xff0c;欢迎来到小雅兰的课堂&#xff0c;今天我们的内容是复习之前的内容&#xff0c;并把之前的内容的一些习题一起来做一做&#xff0c;现在&#xff0c;就让我们进入二分查找的世界吧 首先&#xff0c;我们介绍的题目就是二分查找&#xff0c;也…

module ‘tensorflow‘ has no attribute ‘Session‘

1. module ‘tensorflow‘ has no attribute ‘Session‘ 指定一个会话来运行tensorflow程序&#xff0c;在使用tensorflow1.x版本中用tensorflow.Session即可 但当我的库版本升级到2.x之后&#xff0c;就会出现标题式报错&#xff0c;于是我去查看了tensorflow库的源码&…

使用Keras搭建深度学习模型

前言 目前深度学习领域的主流框架 tensorflowkeraspytorchcaffetheanopaddlepaddle keras 代码架构 keras代码风格相比于其他框架更符合人的思维。 模型 模型的组成分为三部分&#xff1a;输入层、网络层、输出层。 输入层 输入层的作用时规定了模型输入的shape fro…

2022年智源社区年度热点推荐丨新春集锦

本文为2022年最受智源社区小伙伴喜爱的文章&#xff0c;根据文章质量和热门程度等维度计算得出。还有AI大佬的全年总结盘点总结&#xff0c;也一并推荐给你。虎年除旧&#xff0c;兔年迎新&#xff0c;藉此机会、智源编辑组全员谨祝大家新春快乐&#xff01;2022智源社区20篇最…

LINUX学习之网络配置(十一)

1.修改IP地址 使用ifconfig命令 例如要将eth0接口的IP地址更改为192.168.1.100&#xff0c;你可以使用以下命令 ifconfig eth0 192.168.1.100如果你想为IP地址设置子网掩码&#xff0c;可以使用“netmask”参数。例如&#xff0c;要将eth0接口的子网掩码设置为255.255.255.0…

[Linux]进程优先级 Linux中的环境变量

&#x1f941;作者&#xff1a; 华丞臧. &#x1f4d5;​​​​专栏&#xff1a;【LINUX】 各位读者老爷如果觉得博主写的不错&#xff0c;请诸位多多支持(点赞收藏关注)。如果有错误的地方&#xff0c;欢迎在评论区指出。 推荐一款刷题网站 &#x1f449; LeetCode刷题网站 文…

liunx centos9中安装Redis数据库,并在win10中连接redis图文详解

首先我们去Redis的官网点击download下载tar的压缩包 https://redis.io/download/#redis-downloads 用xftp将安装包上传到你的liunx服务器本地地址 解压 tar -xvf /root/redis-7.0.8.tar.gz cd进入你刚才解压的文件夹中 cd /root/redis-7.0.8 执行make进行编译 编译完成后cd进入…