前言

大家好啊,我是汤圆,今天给大家带来的是《Java中的IO流-入门篇》,希望对大家有帮助,谢谢

由于Java的IO类有很多,这就导致我刚开始学的时候,感觉很乱,每次用到都是上网搜,结果每次用完就忘;

后来沉下心去看书学习,才明白都是有规律的;

这里先做个简单的介绍,作为入门级教程,后面还有很多要学习的,有空再整理吧。

简介

文件IO流,主要有两种方式

  1. 字节流:基于普通的Java对象,仅适用于Java程序之间的读写

  2. 字符流:基于普通的文本字符串,不仅适用于Java程序之间的读写,也适用于Java程序和其他语言程序之间的读写

本例中用到的相关类如下:

所有的读写操作都是针对内存而言的,因为程序就是运行内存

读操作就是从磁盘文件或网络流读到内存,对于内存而言就是Input

写操作就是从内存写到磁盘文件或网络流,对于内存而言就是Output

下面分别介绍这两种方式

字节流:基于普通的Java对象

字节流的读和写都是基于Java程序而言,比如在一个机器上的Java程序写入一个对象到文件,然后传输到另一个机器上的Java程序去读取文件中的对象

写入Java对象时,会先将Java对象序列化(对象转为字节),然后写入

读取Java对象时,会先将Java对象反序列化(字节转为对象),然后读取

写对象

将对象写入到文件中,需要先把对象序列化,然后再把序列化后的字节写入到文件中;

序列化就是将对象的属性信息转为一系列字节(不包括transient 类型的属性,下面会介绍)

大概流程如下所示:

读对象

将对象从文件中读出来,需要先反序列化,然后再转为对应的Java对象,并恢复对象属性值

反序列化就是将一系列字节转为真实的对象实例(不包括transient类型的属性)

大概流程如下所示:

transient

该修饰符 字面意思是瞬时的,短暂的

用在对象的属性上,就表示这个属性是暂时有效的,等序列化的时候会失效

在反序列化的时候,这个属性就会为null(如果属性是对象引用)或基础类型的默认值(如果属性是基础类型)

比如密码等比较隐私的属性,我们就可以设置为transient,这样就不会在传输过程中被被人拦截,从而破解出密码

代码


public class ObjectIoDemo {

   public static void main(String[] args) throws IOException, ClassNotFoundException {
       InnerObject object1 = new InnerObject(10);
       String filename = "object.bin";
       writeObjectFun(filename, object1);
       InnerObject objectReturn = (InnerObject) readObjectFun(filename);
       System.out.println(objectReturn);

  }

   // 写对象 到指定文件
   public static void writeObjectFun(String filename, Object o) throws IOException {
       FileOutputStream fileOutputStream = new FileOutputStream(filename);
       ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
       objectOutputStream.writeObject(o);
       // 关闭流,fileOutputStream会一并关闭
       objectOutputStream.close();
  }

   // 读对象 从指定文件
   public static Object readObjectFun(String filename) throws IOException, ClassNotFoundException {
       FileInputStream fileInputStream = new FileInputStream(filename);
       ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
       Object o = objectInputStream.readObject();
       // 关闭流,fileInputStream会一并关闭
       objectInputStream.close();
       return o;
  }
}
class InnerObject implements Serializable{

   @Override
   public String toString() {
       return "InnerObject{" +
               "num=" + num +
               '}';
  }

   public InnerObject(int num) {
       this.num = num;
  }

   public int getNum() {
       return num;
  }

   public void setNum(int num) {
       this.num = num;
  }

   private int num;
}

如果要写入的Java对象没有序列化,则会报错如下

Exception in thread "main" java.io.NotSerializableException: com.jalon.basic.io.InnerObject
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at com.jalon.basic.io.ObjectIoDemo.writeObjectFun(ObjectIoDemo.java:28)
at com.jalon.basic.io.ObjectIoDemo.main(ObjectIoDemo.java:19)

字符流:基于普通文本字符串

字符流写入到文件中的数据,是作为通用文本数据来处理的,这样Java程序和其他程序都可以去读写这个文件

写文本

大致流程如下:

读文本

大致流程如下:

BufferedReader和BufferedWriter的作用

为什么要用缓冲区呢?直接用FileReader和FileWriter不也可以吗?

如果直接用FileWriterFileReader是可以运行,只不过效率会比较低,因为每一次的读写都是针对磁盘操作的;

BufferedWriterBufferedReader这两个缓冲区可以减少磁盘的读写次数;

BufferedReader:程序可以从磁盘一次性读很多数据到缓冲区,再从缓冲区一次次读,等缓冲区为空时再去磁盘读;

BufferedWriter:程序可以写多次到缓冲区,等缓存区满了再一次性写入到磁盘中

代码


public class TextIoDemo {
   public static void main(String[] args) throws IOException {
       String filename = "string.txt";
       writeString(filename, "hello world");
       String res = readString(filename);
       System.out.println(res);
  }
// 写字符串到指定文件
   public static void writeString(String filename, String content) throws IOException {
       FileWriter fileWriter = new FileWriter(filename);
       BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
       bufferedWriter.write(content);

       bufferedWriter.close();
  }
// 从指定文件读取字符串
   public static String readString(String filename) throws IOException {
       FileReader fileReader = new FileReader(filename);
       BufferedReader bufferedReader = new BufferedReader(fileReader);
       String line = "";
       StringBuilder stringBuilder = new StringBuilder();
       while ((line=bufferedReader.readLine())!=null){
           stringBuilder.append(line);
      }
       bufferedReader.close();
       return stringBuilder.toString();
  }
}

总结

IO流分为字节流字符流

如果读写两边都是Java程序,则推荐用字节流,序列化和反序列化很方便

如果一边是Java程序,另一边是其他语言的程序,则推荐用字符流,读写的内容都是文本格式,方便解析

上面只是列出了个别读写类,Java中读写类还有很多,大家感兴趣的可以去java.io下查看

参考

  1. 《Head First Java》(第二版)

  2. 《Java 核心技术卷一》(第十版)

  3. 《Java 编程思想》(第四版)

后记

最后,感谢大家的观看,谢谢

Java中的IO流 - 入门篇的更多相关文章

  1. Java中的IO流之输入流|乐字节

    亲爱的乐字节的小伙伴们,小乐又来分享Java技术文章了.上一篇写到了IO流,这篇文章着重 谈谈输入流,再下次再说输出流. 点击回顾上一篇:乐字节Java之file.IO流基础知识和操作步骤 一. 输入 ...

  2. Java中的IO流(五)

    上一篇<Java中的IO流(四)>记录了一下Properties类,此类不属于IO流,它属于集合框架.接下来说一下IO流中的其它流 一,打印流PrintStream PrintStream ...

  3. Java中的IO流(六)

    上一篇<Java中的IO流(五)>把流中的打印流PrintStream,PrintWriter,序列流SequenceInputStream以及结合之前所记录的知识点完成了文件的切割与文件 ...

  4. Java中的IO流(四)

    上一篇<Java中的IO流(三)>把IO流中的文件及目录操作的对象File类记录了一下,本篇把本不属性IO流但又和IO流有关系的一个对象作一下记录,此对象本属于集合框架里的一个子集,即Pr ...

  5. Java中的IO流(三)

    上一篇<Java中的IO流(二)>把学习Java的字符流以及转换流作了一下记录,从本篇开始将把IO流中对文件或文件夹操作的对象File类的学习进行一下记录. 一,File类的构造函数及字段 ...

  6. Java中的IO流(二)

    上一篇<Java中的IO流(一)>把学习IO流的字符流作了一下记录,本篇把字节流记录一下. 一,Java中的字节流 Java中的字节流的操作方式与字符流的操作方式大致相同,连方法名都是类似 ...

  7. Java中的IO流之输出流|乐字节

    大家好,乐字节小乐又来了.上一篇给大家带来的是:Java中的IO流之输入流|乐字节,本文将继续讲述IO流之输出流.   一.输出流 1.抽象类:OutputStream 和 Writer Output ...

  8. java中的IO流

    Java中的IO流 在之前的时候我已经接触过C#中的IO流,也就是说集中数据固化的方式之一,那么我们今天来说一下java中的IO流. 首先,我们学习IO流就是要对文件或目录进行一系列的操作,那么怎样操 ...

  9. Java中的IO流总结

    Java中的IO流总结 1. 流的继承关系,以及字节流和字符流. 2. 节点流FileOutputStream和FileInputStream和处理流BufferedInputStream和Buffe ...

随机推荐

  1. 技术分享: Canvas 系列

    技术分享: Canvas 系列 SVG 导出 分享截图 加密水印 游戏 场馆图,选派选座 refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可 ...

  2. 你不知道的 JS (系列丛书) - 第二版

    你不知道的 JS (系列丛书) - 第二版 You Don't Know JS (book series) - 2nd Edition https://github.com/learning-js-b ...

  3. angular-2-tutorial-2017

    # angular-2-tutorial-2017https://www.sitepoint.com/understanding-component-architecture-angular/http ...

  4. rename github

    rename GitHub github repo rename xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!

  5. WEB 使用lazysizes延迟加载图像

    原文 Native lazy-loading for the web Example <style> div { height: 3000px; } </style> < ...

  6. TCP编程详解

    目录 数据包格式 建立连接(三次握手) 数据传输 断开连接(四次挥手) 基础 客户端流程 编码 TCP服务端流程 TCP服务端编码 参考文献 TCP把连接作为最基本的对象,每一条TCP连接都有两个端点 ...

  7. [转]ROS 传感器消息及RVIZ可视化Laserscan和PointCloud

    https://blog.csdn.net/yangziluomu/article/details/79576508 https://answers.ros.org/question/60239/ho ...

  8. 翻译:《实用的Python编程》02_02_Containers

    目录 | 上一节 (2.1 数据类型) | 下一节 (2.3 格式化) 2.2 容器 本节讨论列表(list),字典(dict)和集合(set). 概述 通常,程序必须处理许多对象. 股票的投资组合 ...

  9. vue版本一直是2.9.6版本,卸载也卸载不掉,更新也更新不了

    原文链接:https://blog.csdn.net/zlzbt/article/details/110136755 主要是找到本地文件 E:\StudyFile\VueStudy λ where v ...

  10. Linux下安装mysql-5.7.28详细步骤

    一.下载Mysql 下载地址:https://downloads.mysql.com/archives/community/ 二.环境配置 检测系统是否自带Mysql # rmp -qa|grep m ...