Java中的IO流如何理解——精简

2023-11-19

目录

引言

缓冲流 

字节缓冲流 

字符缓冲流 

转换流 

字符输入转换流 

字符输出转换流 

序列化和反序列化 

对象序列化 

对象反序列化 

打印流 

Properties


引言

通过前面的简单学习,我们已经能够大致了解了关于文件的操作,但是能够明显感受到在执行其他的操作的时候,还是会有一些不方便的地方存在,因此今天我们会学习另外四个IO流来帮助我们对文件进行操作,这四个流分别是缓冲流转换流序列化打印流。好了,废话不多说,我直接开始今天的学习吧!

缓冲流 

  • 缓冲流也称为高效流、或者高级流。之前学习的字节流也可以称为原始流。
  • 作用:缓冲流自带缓冲区,可以提高原始字节流、字符流读取数据的性能。
  • 形象举例:倘若我们将对文件的输入和输出操作想象为运输水的过程的话,在最初的时候,水(数据)是直接对接水管进行运输,而缓冲流的不同之处在于水不需要对接水管,仅需要和水管前的水缸进行对接,这么做可以提高了运输的效率。
  • 缓冲流分为两种,一种是字节缓冲流,另一种则是字符缓冲流。分别是BufferedInputStream(字节缓冲输入流)BufferedOuputStream(字节缓冲输出流)BufferedReader(字符缓冲输入流)BufferedWriter(字符缓冲输出流)。 

字节缓冲流 

  • 字节缓冲输入流:BufferedInputStream,提高字节输入流读取数据的性能,读写功能上并无变化
  • 字节缓冲输出流:BufferedOutputStream, 提高字节输出流读取数据的性能,读写功能上并无变化
构造器 说明

public BufferedInputStream(InputStream is)

可以把低级的字节输入流包装成一个高级的字节缓冲输入流管道,从而提高字节输入流读数据的性能
public BufferedOutputStream(OutputStream os) 可以把低级的字节输出流包装成一个高级的字节缓冲输出流管道,从而提高写数据的性能
InputStream is = new FileInputStream("File//data.txt");
InputStream bis = new BufferedInputStream(is);
OutputStream os = new FileOutputStream("File//data01.txt");
OutputStream bos = new BufferedOutputStream(os);
int len;
byte []buffer = new byte[1024];
while ((len = bis.read(buffer))!=-1){
bos.write(buffer,0,len);
bos.flush();

通过字节缓冲流实现将一个文件中的内容复制在另一个文件之中。

字符缓冲流 

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

构造器 说明
public BufferedReader(Reader r) 可以把低级的字符输入流包装成一个高级的缓冲字符输入流管道,从而提高字符输入流读数据的性能
方法 说明
public String readLine() 读取一行数据返回,如果读取没有完毕,无行可读取返回null
        Reader r = new FileReader("File//data.txt");
        BufferedReader br = new BufferedReader(r);//由于是子类独有的功能,所有不能使用多态创建
        String s;
        byte []buffer = new byte[1024];
        while ((s = br.readLine())!=null){
            System.out.println(s);
        }
//正常情况下会将文件中的数据依次输出;
        Reader r = new FileReader("File//data.txt");
        BufferedReader br = new BufferedReader(r);
        br.readLine();
        br.readLine();
//若文件中的数据不足两行:
//kdirvingJamesJame
//null

字符缓冲输出流:BufferedWriter,提高字符输出流写取数据的性能,除此之外多了换行功能 

构造器 说明
public BufferedWriter(Writer w) 可以把低级的字符输出流包装成一个高级的缓冲字符输出流管道,从而提高字符输出流写数据的性能
方法 说明
public void newLine() 执行操作
        Writer w = new FileWriter("File//data.txt",true);
        BufferedWriter bw = new BufferedWriter(w);//由于是子类独有的功能,所有不能使用多态创建
        bw.write("石原里美");
        bw.newLine();
        bw.write("工藤静香");
        bw.newLine();
        bw.flush();

需要留意的地方是,在写文件的时候如果想要对文件进行追加操作,需要对Writer的对象设置true,而不是BufferedWriter的对象。

转换流 

在学习转换流之前,我们应该要了解的是如果代码编码和文件编码如果不一致。使用字符流直接读取会造成乱码,因此我们需要代码编码和文件编码一致,才能保证不会乱码,而转换流的出现就是为了能够避免这种事情的发生的。 

字符输入转换流 

首先是对于乱码的问题提供一个简单的思路:

1、使用字符输入转换流;

2、可以提取文件(不同的编码)的原始字节流,原始字节不会存在问题;

3、将字节流以指定编码转换成字符输入流,这样字符输入流中的字符就不会乱码了。

字符输入转换流:InputStreamReader,可以把原始字节流按照指定编码转换成字符输入流

构造器 说明
public InputStreamReader(InputStream is) 可以把原始的字节流按照代码默认编码转换成字符输入流。几乎不用
public InputStreamReader(InputStream is,String charset) 可以把原始的字节流按照指定指定编码转换成字符输入流,这样字符流中的字符就不乱码了

        InputStream is = new FileInputStream("File//data.txt");
        InputStreamReader isr = new InputStreamReader(is);
        InputStreamReader isr = new InputStreamReader(is,"GBK");

在以上代码中,已知将data.txt文件的编码格式设置为GBK,而代码编码是utf-8,所以需要通过转换流将编码变为一致。而一种构造器默认utf-8,显然是不行的,第二种则是可以指定编码,将原始的字节输入流转换为字符输入流,并以GBK的形似进行读取。

字符输出转换流 

字符输出转换流:OutputStreamWriter,可以把字节输出流按照指定编码转换成字符输出流

构造器 说明
public OutputStreamWriter(OutputStream os) 可以把原始的字节输出流按照代码默认编码转换成字符输出流,几乎不用
public OutputStreamWriter(OutputStream os,String charset) 可以把原始的字节输出流按照指定的编码转换成字符输出流

首先我们应该知道字符输出转换流是为了应对哪些现实中的事情:假如你的客户智能编码为GBK的文件,那么你给他传过去一个utf-8的文件的话,文件是会乱码的,那么这个时候就需要我们传过去一个编码为GBK的文件。

        OutputStream os = new FileOutputStream("File//data.txt");
        Writer osw = new OutputStreamWriter(os);
        Writer osw = new OutputStreamWriter(os,"GBK");

在以上代码中,第一种是默认utf-8的,所以是几乎不用的,而第二种则是可以指定客户需要的编码文件格式。

序列化和反序列化 

对象序列化 

  • 对象字节输出流,ObjectOutputStream
  • 作用:以内存为基准,把内存中的对象存储到磁盘文件中去,称为对象序列化
构造器 说明
public ObjectOutputStream(OutputStream os) 把低级字节输出流包装成高级的对象字节输出流

 首先是简单的创建了一个学生类Student,需要注意的是Java规定对象序列化的时候,类需要实现Serializable接口

public class Student implements Serializable {
    private String name;
    private int age;
    private String number;
    private String classroom;
}

接下来则是实现对象的序列化的操作:

        Student s = new Student("石原里美",18,"001","智能一班");
        OutputStream os = new FileOutputStream("File//data.txt");
        ObjectOutputStream oos = new ObjectOutputStream(os);
        oos.writeObject(s);
        oos.close();

另外如果不希望对象中的某个数据不参与序列化,则可以通过transient对其进行修饰,如“private transient String name”,执行该操作之后,对其进行反序列化的时候该数据会显示null。

对象反序列化 

  • 对象字节输入流,ObjectInputStream
  • 作用:以内存为基准,把存储到磁盘文件中去的对象数据恢复成内存中的对象,称为对象反序列化
构造器 说明
public ObjectInputStream(InputStream is) 把低级字节输入流包装成高级的对象字节输入流
方法名称 说明
public Object readObject() 把存储到磁盘文件中去的对象数据恢复成内存中的对象返回
        InputStream is = new FileInputStream("File//data.txt");
        ObjectInputStream ois = new ObjectInputStream(is);
        Object s = ois.readObject();
        System.out.println(s);
//输出结果:
//Student{name='石原里美', age=18, number='001', classroom='智能一班'}

另外还有一个知识点,在定义类的时候,可以定义一个版本序列号,而在反序列号的时候,其序列号必须一致才可以正常的读取,如“private static final long serialVersionUID = 1;”

若在第一次序列化之后,将类中的版本序列号更改,在没有作第二次重新序列化之前,反序列化会出现报错的情况。

打印流 

  • 作用:打印流可以实现方便、高效的打印数据到文件中去。一般指PrintStream,WriteStream两个类
  • 可以实现打印什么数据就是什么数据,例如打印整数97,写出去就是97,打印boolean的true,写出去就是true
构造器 说明
public PrintStream(OutputStream os) 打印流直接通向字节输出流管道
public PrintStream(File f) 打印流直接通向文件对象
public PrintStream(String filepath) 打印流直接通向文件路径
方法名称 说明
public void print(Xxx xx) 打印任意类型的数据出去

//三种构造器的使用
PrintStream ps = new PrintStream("File//data01.txt");
PrintStream ps1 = new PrintStream(new File("File//data.txt"));
PrintStream ps2 = new PrintStream(new FileOutputStream(new          File("File//data.txt")));
ps.print(11);
ps.print("凯里·欧文");

PrintStream和WriterStream的区别

  • 打印数据功能上是一模一样,都是使用方便,性能高效
  • PrintStream继承字节输出流OutputStream,支持写字节数据的方法
  • PrintWriter继承字符输出流Writer,支持写字符出去

Properties

  • 作用:Properties代表的是一个属性文件可以把自己对象中的键值对信息存入到一个属性文件中去
  • 属性文件:后缀是.properties结尾的文件,里面的内容都是key=value,后续做系统配置信息的

构造器 说明
void load (InputStream is) 从输入字节流读取属性列表(键值对)
void load (Reader r) 从输入字符流读取属性列表(键值对)
void store (OutputStream os,String comments) 将此属性列表(键值对)写入此Properties中,以适合于使用load(InputStream)方法的格式输出字节流
void store(Writer w,String comments) 将此属性列表(键值对)写入此Properties中,以适合于使用load(reader)方法的格式输出字符流
public Object setProperty(String key,String value) 保存键值对(put)
public String getProperty(String key) 使用此属性列表中指定的键搜索属性值(get)
public Set<String> stringPropertyNames() 所有键的名称的集合(keySet())
        Properties properties = new Properties();
        properties.setProperty("石原里美","18");
        properties.setProperty("工藤静香","19");
        properties.setProperty("朱茵","20");
        System.out.println(properties);
        //第一个参数是文件存储路径,第二个是对文件的注释
        properties.store(new FileWriter("File//Baby.properties"),"这些都是绝世美女,不接受反驳哈哈哈");

        Properties properties = new Properties();
        properties.load(new FileReader("File//Baby.properties"));
        System.out.println(properties);
//输出结果:
//{"石原里美"=18,"工藤静香"=19,"朱茵"=20}

创作不易,给个三连吧

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java中的IO流如何理解——精简 的相关文章

  • 在Java中清空数组/处理

    除了循环遍历数组中的每个元素并将每个元素设置为 null 之外 Java 处理中是否有一个本机函数可以简单地清空数组 或销毁它 以便能够将其重新声明为新数组 There s Arrays fill myArray null 并不是说它执行的
  • 在 IntelliJ 上进行 Google App Engine Java 开发?

    令人烦恼的是 Google App Engine 已成为其中的另一个项目 他们只发布 Eclipse 插件 如 Spring Webflow 而我更喜欢 IntelliJ 你能用IntelliJ成功运行本地测试环境吗 并调试 部署本地或实时
  • 线程“main”java.lang.UnsatisfiedLinkError中出现异常:java.library.path中没有opencv_java249

    我目前正在尝试在我的 32 位笔记本电脑上设置 OpenCV 但我不断收到一条令我困惑的错误消息 Exception in thread main java lang UnsatisfiedLinkError no opencv java2
  • 使用 Spring Data REST 处理自定义异常 (i18n)

    我正在使用 Spring Boot 1 5 4 和 Spring JPA Spring Data REST HATEOAS 我正在寻找一种最佳实践 Spring 方式 来自定义异常 Spring Data REST 正在管理添加 i18n
  • 使用 jpql 和 jpa 从日期字段中提取年份

    我想从数据库中的一行中提取年份部分 以便将其与值进行比较 这是我的功能 public List
  • 如何测试调用父类的受保护(不需要的)方法的方法?

    我陷入了一个非常奇怪的情况 我有一些需要测试的特定代码 这里是 public class A The real method of real class is so big that I just don t want to test it
  • 如何识别 Java 中的不可变对象

    在我的代码中 我正在创建一个对象集合 这些对象将由各种线程以只有在对象不可变的情况下才安全的方式访问 当尝试将新对象插入到我的集合中时 我想测试它是否是不可变的 如果不是 我将抛出异常 我能做的一件事是检查一些众所周知的不可变类型 priv
  • firebase推送通知错误Spring Boot服务器端

    我正在尝试从 Spring Boot 服务器端发送通知到客户端 android 服务器运行良好 一切都很好 2020 09 01 08 13 07 691 INFO 18941 restartedMain e DevToolsPropert
  • 初级 Java 计数器代码

    我的教授希望我这样做 使用下面的 Counter 接口写入多个可互换计数器 public interface Counter Current value of this counter int value Increment this co
  • Java Spring 应用程序存在内存泄漏。系统非堆内存不断增加

    我已使用 yourkit 分析器监视我的 Web 应用程序 保留最大大小的主要对象是 SessionFactoryImpl webappclassloader 和 CGlib 对象显示 spring crone调度程序会导致内存泄漏吗 我尝
  • 如何将自定义日志处理程序添加到 Google App Engine?

    我正在尝试向我的 java 应用程序添加自定义日志处理程序 我已经实现了一个扩展 java util Logging Handler 类的 InnerLogger 类 在我的logging properties中声明为处理程序 handle
  • C# 中的协变和逆变

    首先我要说的是 我是一名正在学习 C 编程的 Java 开发人员 因此 我会将我所知道的与我正在学习的进行比较 我已经使用 C 泛型几个小时了 我已经能够在 C 中重现我在 Java 中知道的相同内容 除了几个使用协变和逆变的示例 我正在读
  • Java:使用 Java.util.concurrent 线程访问读取线程串行端口

    我正在尝试编写一个 Java 串行设备驱动程序并想使用 对我来说是新的 java util concurrent包裹 我有一种发送数据包然后等待 ACK 的方法 我打算有炭 接收在不同的线程中运行 如果接收线程收到 ACK 它应该使用发送数
  • 如何从 Google Custom Search API 获取超过 100 个结果

    我正在尝试使用 Google Custom Search API 在 Java 中进行研究 因此 我需要为每个查询提供一个大的结果集 然而 我似乎仅限于前 100 个结果 这比我需要的要少得多 我使用这样的列表方法 list setStar
  • 使用Java开发跨平台,不同平台字体缩放不同

    我正在为我的大学制作一些软件 需要一个 GUI 在它的第一个版本中 我让它使用系统外观 因此它看起来像 Linux Mac Windows 中的本机应用程序 我发现这很麻烦 因为我必须根据操作系统使所有 JLabel 具有不同的大小 无论分
  • 为什么现在()? (客观化)

    为什么我想要异步加载 Objectify 实体 异步加载到底意味着什么 根据客观化有关加载的文档 https code google com p objectify appengine wiki BasicOperations Loadin
  • 如何从spark中的hbase表中获取所有数据

    我在 hbase 中有一个大表 名称为 UserAction 它具有三个列族 歌曲 专辑 歌手 我需要从 歌曲 列族中获取所有数据作为 JavaRDD 对象 我尝试了这段代码 但效率不高 有更好的解决方案来做到这一点吗 static Spa
  • 编写自定义 Eclipse 调试器

    EDIT 一定有某种方法可以解决这个问题 而无需编写全新的调试器 我目前正在研究在现有 java 调试器之上构建的方法 如果有人对如何获取 Java 调试器已有的信息 有关堆栈帧 变量 原始数据等 有任何想法 那将非常有帮助 我想要做的是我
  • 如何使用剪辑来减少绘画时间?

    我正在尝试使用 Clip 来减少 CPU 负载 但剪辑在屏幕上留下了一些我似乎无法摆脱的垃圾 另外 打开和关闭剪辑似乎对 CPU 负载没有影响 在任一情况下 大部分时间似乎都花在重绘管理器和绘制缓冲图像上 import static jav
  • 我找不到 IntelliJ 快捷方式

    我使用 vim 一段时间 我知道有一个 intellij vim 插件 我很好奇内置的 IntelliJ 文本导航存在什么 如何打开实时模板来创建模板 如何查看以 tr 开头的现有模板列表 如何进行全局搜索并在当前文档中进行搜索 然后转到下

随机推荐

  • 01、Java并发 Java ExecutorService

    ExecutorService 是 Java java util concurrent 包的重要组成部分 是 Java JDK 提供的框架 用于简化异步模式下任务的执行 一般来说 ExecutorService 会自动提供一个线程池和相关
  • 程序员如何做副业?35岁前,千万别让死工资绊住你赚钱的步伐

    近年来互联网行情下降 好多人都在思考要不要搞个副业来抵御风险 这不又来事了 这两天又爆了互联网大裁员 继阿里 向社会输送人才 之后 京东又搞了个 毕业礼 整的小伙伴们人心惶惶 副业的关注度又一波升级 那今天我们就来聊聊 程序员做副业这件事
  • cef编译

    按照大神的一遍过 具体过程非常详细 链接https kefong blog csdn net article details 119908780 spm 1001 2101 3001 6650 2 utm medium distribute
  • 《C++ Primer(第5版)》学习笔记(第5章)

    第5章 语句 C 提供了条件执行语句 循环语句和用于中断当前控制流的跳转语句 本章将具体介绍这些语句 5 1 简单语句 空语句 最简单的语句是空语句 只有一个单独的分号 如在程序的某个地方语法上需要一条语句但是逻辑上不需要 此时应该使用空语
  • 透过Python 将接收邮件邮件进行分类统计

    工作的需要自行学习了Python的一些功能 将所学的经验在这里分享给大家 文章目录 目录 文章目录 前言 一 环境准备 二 使用步骤 1 引入库 2 读入数据 总结 前言 工作中我们可能会透过邮件 让其他公司收集资料 在学会Python之前
  • 全网最最最轻量级检测网络 yolo-fastest 快速上手

    文章目录 0x01 Yolo Fastest 0x02 Prepare step1 clone step2 make step3 run darknet 0x03 Train step1 获取权重文件 step2 准备数据集 step3 修
  • 成功上岸字节35K,技术4面+HR面,耗时20天,真是不容易

    这次字节的面试 给我的感触很深 意识到基础的重要性 一共经历了五轮面试 技术4面 HR面 下面看正文 本人自动专业毕业 压抑了五个多月 终于鼓起勇气 去字节面试 下面是我的面试过程 很多面试题 都是靠记忆写的 希望能帮助到大家 致那些努力的
  • 初步认识操作系统(Operator System)

    操作系统 一 冯诺依曼体系结构 内存的重要作用 二 操作系统的概念 三 设计操作系统的目的 三 操作系统在计算机体系中的定位 四 操作系统是如何进行管理的 一 冯诺依曼体系结构 在众多计算机相关的书籍中 不得不提的就是冯诺依曼体系结构 冯诺
  • 无需魔法三分钟上线Midjourney应用,【附源码】【示例】

    ps 我是标题党 目前还没见过三分钟完成任务的 三分钟只能打通Midjourney接口 我花了一天时间接入应用哈哈哈 首先 我要感谢laf赞助我 让我可以免费使用Midjourney进行开发和测试 来自白嫖党的快乐 其次 我要感谢白夜 米开
  • Linux驱动编程(总线设备驱动模型)

    一 驱动编写的3种方法 1 传统写法 使用哪个引脚 怎么操作引脚 都写死在代码中 最简单 不考虑扩展性 可以快速实现功能 修改引脚时 需要重新编译 2 总线设备驱动模型 引入 platform device platform driver
  • 最近opencv又报了啥错(一)

    前言 别骂了别骂了 太久没打python 手贼生 最近在搞opencv和一些ocr 报了一堆错 有些是python的原生错误 有的是opencv的 有的是我nt 就全部记录一下吧 1 bad argument type for built
  • 端口监控信息

    netstat nlptu grep 8080 一 0 0 0 0 8080 代表8080端口 对内网和外网都是开放的 tcp 0 0 0 0 0 0 8080 0 0 0 0 LISTEN 123941 java 二 查看网卡的代码 da
  • KVM中使用usb设备

    进来学习usb驱动 看到网上都在分析usb skeleton c的驱动框架 就想对其调试一下 看一下其函数调用流程 要想调试usb skeleton 首先需要kvm能够探测到usb设备 其次 在kvm中编译usb skeleton c 最后
  • 深度学习要学多久?半年能入门深度学习吗?

    深度学习的学习时间因个人背景 目标和学习方法而异 不同人可能需要不同的时间来掌握深度学习 深度学习要学多久 通常情况下 入门深度学习可能需要几个月的时间 如果你已经有相关背景知识 学习进度可能会更快 以下是一些因素 可以影响学习深度学习所需
  • 解一元二次方程-Java语言实现

    前言 高考完的那个暑假我就开始自学C语言 那时候通过看视频和 C primer plus 写了一个解一元二次方程的程序 从此走上了吊打大学同班同学的路 但是那次是用C语言写的 如今白云苍狗 我已经不是曾经的那个我了 但我还是一如既往的废物
  • Java的内省技术

    什么是内省 在计算机科学中 内省是指计算机程序在运行时 Run time 检查对象 Object 类型的一种能力 通常也可以称作运行时类型检查 不应该将内省和反射混淆 相对于内省 反射更进一步 是指计算机程序在运行时 Run time 可以
  • 大数据面试-03-大数据工程师面试题

    2 13 简述hadoop的调度器 FIFO schedular 默认 先进先出的原则 Capacity schedular 计算能力调度器 选择占用最小 优先级高的先执行 依此类推 Fair schedular 公平调度 所有的job具有
  • 三十三.二叉树的创建、后序遍历、深度统计。

    include
  • 【视频编码学习】VTM15.0编译运行

    VTM版本 15 0 操作系统 Win10 x64位 IDE Visual Studio 2019 编译器 cmake 利用VS2019运行VTM15 0 前言 一 下载VTM15 0 二 下载安装cmake 1 下载cmake并安装 2
  • Java中的IO流如何理解——精简

    目录 引言 缓冲流 字节缓冲流 字符缓冲流 转换流 字符输入转换流 字符输出转换流 序列化和反序列化 对象序列化 对象反序列化 打印流 Properties 引言 通过前面的简单学习 我们已经能够大致了解了关于文件的操作 但是能够明显感受到