什么是IO,初级Java怎么更好的理解IO流(上)

(注:本篇文章分为两个部分,如果想更为深刻的了解IO,请关注下一篇;欢迎大家学习讨论和批评指正)

IO1

作用

将数据在虚拟机内存和本地磁盘之间进行传输

I:input 输入

O:output 输出

相当于管道,作用为进行数据传输

分类

  1. 从传输方向上看

    • 输入流:本地磁盘的数据向JVM传输
    • 输出流:JVM数据向本地磁盘传输
  2. 从传输单位上看

    • 字节流:以字节为单位进行数据传输。可以传输任意类型的数据,如文本、图片、视频、音频等
    • 字符流:以字符为单位进行数据传输。只能传输文本类型的数据,如.txt、.java、.html等
  3. 从传输功能上看

    • 节点流:具有传输功能和意义的流
    • 过滤流:没有传输功能,用来给节点流增强传输能力或增加附加功能

字节流

  • 输入流:InputStream 抽象父类
  • 输出流:OutputStream 抽象父类

输入流

  • 节点流:FileInputStream
创建
FileInputStream fis=new FileInputStream("本地的文件路径");
  • 路径:

    • 绝对路径:以电脑磁盘为基点的完整路径

      FileInputStream fis = new FileInputStream("D:\\test\\a.txt");
      FileInputStream fis = new FileInputStream("D:/test/a.txt");
      
    • 相对路径:以当前项目路径为基点的路径,前提是文件必须在项目下

      FileInputStream fis = new FileInputStream("file\\a.txt");
      FileInputStream fis = new FileInputStream("file/a.txt");
      
    • 路径书写必须截至至文件

    • 文件必须存在,否则抛出异常

常用方法
  1. void close():关闭流链接,释放相关资源。(每个流中都有)
  2. int read(): 读取一个字节返回,读取到达末尾,返回-1
  3. int read(byte[] b): 尝试读取数组长度的数据至数组中, 返回实际读取个数.读取到达末尾,返回-1
package com.by.test;import java.io.FileInputStream;public class TestFIS {public static void main(String[] args)throws Exception {// FileInputStream fis = new FileInputStream("D:\\test\\a.txt");//  FileInputStream fis = new FileInputStream("D:/test/a.txt");// FileInputStream fis = new FileInputStream("C:\\Users\\Administrator\\IdeaProjects\\Chp16\\file\\a.txt");FileInputStream fis = new FileInputStream("file\\a.txt");//FileInputStream fis = new FileInputStream("file/a.txt");//读取一个字节//利用循环读取文件所有内容while (true) {//先接收本次读取内容int n = fis.read();//判断读取是否到达末尾if (n == -1) {break;}//未到达末尾,输出查看System.out.println((char) n);}//利用read(byte[])+循环读取文件所有内容while (true) {byte[] bs = new byte[3];//接收本次读取结果int n = fis.read(bs);//判断读取是否到达末尾if (n == -1) {break;}//遍历数组查看本次读取结果for (int i = 0; i < bs.length; i++) {System.out.println(bs[i]);}}//关流fis.close();System.out.println("执行成功!");}
}

输出流

  • 节点流:FileOutputStream
创建
FileOutputStream fos=FileOutputStream("本地的文件路径",true|false);
  • 如果文件不存在,会自动创建
    • 无法创建文件夹
  • true表示数据追加,false表示数据覆盖
    • 默认是false
常用方法
  1. void flush(): 刷新缓冲区,所有输出流中都具备该方法
  2. void write(int ): 向目标文件写入一个字节
  3. void write(byte[] ): 向目标文件写入一个数组的数据
package com.by.test;import java.io.FileOutputStream;public class TestFOS {public static void main(String[] args)throws Exception {FileOutputStream fos=new FileOutputStream("file/b.txt");//写入一个字节fos.write(65);fos.write(66);fos.write(67);//写入一个数组String str = "abcdefg123456";byte[] bs = str.getBytes();fos.write(bs);//关流fos.close();System.out.println("执行成功!");}
}

标准异常处理

  • JDK7.0之后,提供了自动关流的语法结构,简化了finally的工作内容
try(//需要自动关流的创建语句
){}catch(){}
  • 原理: JDK7.0之后,所有的流都默认实现了AutoCloseable接口,该接口中提供了自动关流所需的close方法
package com.by.test;import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;public class TestFOS2 {public static void main(String[] args) {try (FileOutputStream fos = new FileOutputStream("file/b.txt");){//写入一个字节fos.write(65);fos.write(66);fos.write(67);//写入一个数组String str = "abcdefg123456";byte[] bs = str.getBytes();fos.write(bs);} catch (FileNotFoundException e) {System.out.println("文件路径不正确");} catch (IOException e) {System.out.println("读写失败");} catch (Exception e) {System.out.println("未知异常!");e.printStackTrace();}System.out.println("执行成功!");}
}

文件复制

  • 原理: 先将文件A中的内容读取到JVM中,再从JVM中将读取内容写入到文件B, 借助JVM来实现A与B之间的数据复制
    • 先读后写
package com.by.test;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;public class TestFileCopy {public static void main(String[] args) {copy1();copy2();}/*** 一次复制一个字节*/public static void copy1(){try (//创建输出节点流-复制到的文件路径FileOutputStream fos=new FileOutputStream("d:/test/2.pdf");//创建输入节点流-被复制的文件路径FileInputStream fis=new FileInputStream("d:/test/1.pdf")) {//先循环读取文件所有内容while (true) {int n = fis.read();if (n == -1) {break;}//将本次读取的字节写入到目标文件fos.write(n);}System.out.println("复制成功!");} catch (FileNotFoundException e) {System.out.println("文件路径不正确");} catch (IOException e) {System.out.println("读写失败!");} catch (Exception e) {System.out.println("未知异常!");e.printStackTrace();}}/*** 一次复制一个字节数组*/public static void copy2(){try (//创建输出节点流-复制到的文件路径FileOutputStream fos=new FileOutputStream("d:/test/3.pdf");//创建输入节点流-被复制的文件路径FileInputStream fis=new FileInputStream("d:/test/1.pdf")) {//先循环读取文件所有内容while (true) {//创建数组byte[] bs = new byte[1024];//读取一个数组的数据int n = fis.read(bs);if (n == -1) {break;}//将数组中的数据写入到目标文件fos.write(bs);}System.out.println("复制成功!");} catch (FileNotFoundException e) {System.out.println("文件路径不正确");} catch (IOException e) {System.out.println("读写失败!");} catch (Exception e) {System.out.println("未知异常!");e.printStackTrace();}}
}

缓冲过滤流

  • BufferedInputStream: 输入缓冲过滤流
  • BufferedOutputStream: 输出缓冲过滤流

创建

BufferedInputStream bis=new BufferedInputStream(fis对象);
BufferedOutputStream bos=new BufferedOutputStream(fos对象);

作用

拥有一个内置的数据缓冲区, 文件数据将对接至数据缓冲区中,在缓冲区刷新或关闭时再将内部内容一并的给到目标文件

 /*** 一次复制一个字节+缓冲过滤流*/public static void copy3(){try (//创建输出节点流-复制到的文件路径FileOutputStream fos=new FileOutputStream("d:/test/4.pdf");//创建输入节点流-被复制的文件路径FileInputStream fis=new FileInputStream("d:/test/1.pdf");//添加缓冲过滤流BufferedOutputStream bos=new BufferedOutputStream(fos);BufferedInputStream bis=new BufferedInputStream(fis)) {//先循环读取文件所有内容while (true) {int n = bis.read();if (n == -1) {break;}//将本次读取的字节写入到目标文件bos.write(n);}System.out.println("复制成功!");} catch (FileNotFoundException e) {System.out.println("文件路径不正确");} catch (IOException e) {System.out.println("读写失败!");} catch (Exception e) {System.out.println("未知异常!");e.printStackTrace();}}

使用

  1. 如果先写后读,需要在写入完成后刷新缓冲区才能保证读取的正常进行

    • 调用flush():强刷缓冲区 (推荐)
    • 调用close(): 关流之前也会刷新缓冲区
  2. 关流时外层过滤流关闭内层节点流会一并关闭

package com.by.test;import java.io.*;public class TestBuffered {public static void main(String[] args) {try(//输出BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("file/a.txt"));//输入BufferedInputStream bis=new BufferedInputStream(new FileInputStream("file/a.txt"))){//先写bos.write("abcd".getBytes());//刷新缓冲区bos.flush();   //bos.close();//再读while (true) {int n = bis.read();if (n == -1) {break;}System.out.println((char) n);}}catch (FileNotFoundException e) {System.out.println("文件路径不正确");} catch (IOException e) {System.out.println("读写失败!");} catch (Exception e) {System.out.println("未知异常!");e.printStackTrace();}}
}

对象过滤流

  • ObjectInputStream 对象输入过滤流
  • ObjectOutputStream 对象输出过滤流
  • 附加功能1: 读写基本类型
  • 附加功能2: 读写引用类型

读写基本类型

读取: ois.readXxx()
写入: oos.writeXxx();: Xxx对应的为基本类型名,首字母大写
  • 由于对象过滤流底层嵌套了缓冲区,所以先写后读操作时,仍然需要在写入完成后刷新缓冲区
  • 为了保证数据的安全性,所以在写入时数据会根据魔数机制对其加密,在读取时在进行解密
package com.by.test;import java.io.*;public class TestObject_Double {public static void main(String[] args) {try (//输出流ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("file/c.txt"));//输入流ObjectInputStream ois=new ObjectInputStream(new FileInputStream("file/c.txt"))) {//先写oos.writeDouble(10.5);//强刷缓冲区oos.flush();//读取System.out.println(ois.readDouble());} catch (FileNotFoundException e) {System.out.println("文件路径不正确");} catch (IOException e) {System.out.println("读写失败!");e.printStackTrace();} catch (Exception e) {System.out.println("未知异常!");e.printStackTrace();}}
}

读写引用类型

读取: Object ois.readObject()  读取到达末尾,抛出EOFException异常
写入: oos.writeObject(对象)  可以自动刷新缓冲区,所以先写后读时无需进行flush
读写String
package com.by.test;import java.io.*;public class TestObject_String {public static void main(String[] args) {try (//输出流ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("file/c.txt"));//输入流ObjectInputStream ois=new ObjectInputStream(new FileInputStream("file/c.txt"))) {//先写oos.writeObject("床前明月光");oos.writeObject("疑是地上霜");oos.writeObject("举头望明月");oos.writeObject("低头思故乡");//后读while (true) {try {String s =(String) ois.readObject();System.out.println(s);} catch (EOFException e) {//读取到达末尾,跳出循环break;}}} catch (FileNotFoundException e) {System.out.println("文件路径不正确");} catch (IOException e) {System.out.println("读写失败!");e.printStackTrace();} catch (Exception e) {System.out.println("未知异常!");e.printStackTrace();}}
}
读写自定义类型
  • 自定义类必须实现Serializable接口,表示允许被序列化,否则IO流没有读写权限

    序列化:拆分对象信息的过程

    反序列化:通过信息组装对象的过程

  • 将属性通过transient修饰符修饰则可以防止其参与序列化

  • 如果对象中有自定义类型的属性,则必须使该属性类型也实现序列化接口或者通过transient修饰符对其修饰

package com.by.entity;import java.io.Serializable;public class Student implements Serializable {private String name;private int age;//防止被序列化private transient double score;// private Teacher tea;
//省略getter、setter、构造、toString
}
package com.by.test;import com.by.entity.Student;import java.io.*;public class TestObject_Student {public static void main(String[] args) {try (//输出流ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("file/c.txt"));//输入流ObjectInputStream ois=new ObjectInputStream(new FileInputStream("file/c.txt"))) {//先写oos.writeObject(new Student("zhangsan", 20, 88.5));//后读System.out.println((Student)ois.readObject());} catch (FileNotFoundException e) {System.out.println("文件路径不正确");} catch (IOException e) {System.out.println("读写失败!");e.printStackTrace();} catch (Exception e) {System.out.println("未知异常!");e.printStackTrace();}}
}

怎么理解输出语句?

System是类库中的工具类,out为该工具类中的静态属性,类型为标准输出流类型,print和println系列方法是该流中提供的写入方法,作用为向控制台写入一个内容

今日掌握

  1. 流的分类
  2. 文件复制的源码(字节复制+缓冲过滤流)
  3. 对象过滤流读写自定义类型

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

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

相关文章

阿里云ECS云服务器优势整理(共9点)

为什么选择阿里云服务器ECS&#xff1f;选择云服务器ECS&#xff0c;可以轻松构建具有以下九大优势的计算资源&#xff0c;阿里云服务器网aliyunfuwuqi.com分享阿里云官网关于云服务器ECS的九大优势&#xff1a; 无需自建机房&#xff0c;无需采购以及配置硬件设施。分钟级交付…

c++学习笔记(12)-traits

1、概念 C 中的 type traits 是一种模板元编程技术&#xff0c;用于在编译期间判断、查询类型的属性。Type traits 可以帮助程序员在编译时进行类型判断&#xff0c;而不是在运行时判断&#xff0c;避免了程序中的不必要开销&#xff0c;并且可以提供更好的类型安全性。 2、用…

探索 WebRTC:数字世界的实时通信魔法

前言 在当今日常生活中&#xff0c;我们期望能够随时随地与朋友、同事或家人进行实时沟通。WebRTC&#xff08;Web实时通信&#xff09;技术就像一种魔法&#xff0c;让这些交流变得无比便捷&#xff0c;而且完全在浏览器中实现&#xff0c;无需下载任何额外应用或插件。 Web…

Linux Ubuntu安装nodejs

nodejs官网 Linux 安装 node&#xff0c;npm &#xff08;详细图解&#xff09; 步骤 下载 wget https://nodejs.org/dist/v20.10.0/node-v20.10.0-linux-x64.tar.xz 解压 tar -xf node-v20.10.0-linux-x64.tar.xz 重命名 mv node-v20.10.0-linux-x64 node 进目录 cd node/b…

对接日志服务器系统,将业务服务器、数据库服务器等系统日志rsyslog统一推送或接入至日志服务器进行检测及日志的抓取分析。

1、客户端业务系统服务器配置&#xff0c;系统日志配置文件默认存放在/etc/rsyslog.conf下&#xff1b; 2、打开系统日志推送配置&#xff08;其它邮件日志、开机日志、消息日志等都可统一接入&#xff09; 3、配置推送地址和协议 这里特别说明一下&#xff1a;【注意&#xff…

stm32学习笔记:TIM-定时中断和外部时钟

定时器四部分讲解内容&#xff0c;本文是第一部分 ​​​​​TIM简介 基本定时器 时基单元&#xff1a;预分频器、计数器、自动重装载寄存器 预分频器之前&#xff0c;连接的就是基准计数时钟的输入&#xff0c;由于基本定时器只能选择内部时钟&#xff0c;所以可以认为这根…

Unity预设体

目录 预设体是什么&#xff1f; 如何创建预设体&#xff1f; 如何修改预设体&#xff1f; 如何删除预设体&#xff1f; 预设体是什么&#xff1f; Unity中的预设体&#xff08;Prefab&#xff09;是一种可重复使用的游戏对象模板。它允许开发者创建一个或多个游戏对象&…

ES实用的深度解构赋值方法

ES6 中允许按照一定模式&#xff0c;从数组和对象中提取值&#xff0c;对变量进行赋值&#xff0c;这被称为解构&#xff08;Destructuring&#xff09;。使用解构赋值可以将复杂的代码整理的更加干净整洁。 1.解构对象 在没有使用解构之前&#xff0c;想要确定对象中的某些属…

一篇了解Maven中的<optional>和<scope>使用

目录 Maven的依赖传递optional 与 scope 的区别scope 的可选值 Maven的依赖传递 依赖管理是maven提供的主要功能之一&#xff0c;无论我们需要什么依赖&#xff0c;只需将它们添加到 POM.xml 中&#xff0c;在构建或运行时所有必要的类和资源都会自动添加到项目的 classpath 中…

自己开发一种编程语言,可以同时开发鸿蒙,Android ios的三个平台的应用

我想要开发一种可以在&#xff0c;鸿蒙操作系统&#xff0c;Android操作系统&#xff0c;和ios操作系统运行的&#xff0c;编程语言,意思是自己开发一种编程语言,可以同时开发鸿蒙,Android ios的三个平台的应用,请问怎么实现,需要哪些技术,flutter为什么可以开发Android,ios应用…

DVWA靶场中的xss-反射型xss、存储型xss的low、medium、high的详细通关方法

目录 1.DVWA反射型xss &#xff08;1&#xff09;Low&#xff1a; &#xff08;2&#xff09;Medium&#xff1a; &#xff08;3&#xff09;Heigh 2.xss存储型 &#xff08;1&#xff09;Low&#xff1a; &#xff08;2&#xff09;Medium &#xff08;3&#xff09;He…

实现 Spring Boot 项目热重载,无需重启,省时省力

实现 Spring Boot 项目热重载&#xff0c;无需重启&#xff0c;省时省力 插件介绍 通过 JRebel 插件 实现 Spring Boot 项目热重载。类似于前端 Webpack 热重载功能 无需重启&#xff0c;省时省力 安装插件 打开 IDEA 在插件中搜索&#xff1a;JRebel 安装成功后重启IDEA …

1.SQL - 概述

1. SQL语句分类 • 数据定义语言&#xff1a;简称DDL(Data Definition Language)&#xff0c;用来定义数据库对象&#xff1a;数据库&#xff0c;表&#xff0c;列等。关键字&#xff1a;create&#xff0c;alter&#xff0c;drop等 • 数据操作语言&#xff1a;简称DML(Data …

一起玩儿物联网人工智能小车(ESP32)——17. 用ESP32的ADC功能读取电源电压

摘要&#xff1a;本文主要介绍如何使用ESP32的ADC功能&#xff0c;读取物联网智能小车的电池电压 今天介绍一个ESP32的新功能——如何利用ESP32的引脚&#xff0c;采集模拟量信息。在前面GPIO的学习中我们知道&#xff0c;可以利用GPIO的引脚读取外部设备输出的高低电平信号&am…

什么是LangChain

我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版&#xff0c;欢迎购买。点击进入详情 LangChain 是一个旨在简化使用大型语言模型&#xff08;LLM&#xff09;创建应用程序的框架。它提供了许多功能&#xff0c;使与LLM的合作变得更加容易&#xff0c…

【Mybatis】我抄袭了Mybatis,手写一套MyMybatis框架:学会使用mybatis框架

上一篇文章中&#xff0c;我们学习了通过JDBC与MySQL进行交互。如果我们平常在项目中使用mybatis框架作为我们的orm框架。这一次我们就来学习如何使用框架。我们项目中使用到maven。我们直接通过pom文件的方式给他引入进来。 MyBatis是一个简单而强大的持久层框架&#xff0c;…

SParC数据集介绍

导语 SParC是Text-to-SQL领域的一个多轮查询数据集。本篇博客将对该数据集论文和数据格式进行简要介绍。 SParC数据集概述 SParC是一个跨领域的多轮Text-to-SQL数据集。它包含有4298个问题轮次&#xff0c;大约有12k的自然语言问句到SQL标注的Question-SQL对。这些问题来自于…

多汗症是否会遗传?

多汗症确实具有一定的遗传倾向。 首先&#xff0c;多汗症在临床上是比较常见的疾病&#xff0c;并且给生活带来了很多困扰。其中&#xff0c;许多患者多汗症是有遗传倾向的&#xff0c;即这个病本身就有遗传的一个几率。尤其是病理性多汗症&#xff0c;遗传的可能性更大。 具…

JavaWeb的Servlet的入门和使用方法

1 什么是Servlet Servlet是Server Applet的简称&#xff0c;是用Java编写的是运行在 Web 服务器上的程序&#xff0c;它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。使用 Servlet&#xff0c;可以收集来自网页表单的用户输…

提升FTP上传速度的方法(提升FTP下载速度的技巧)

在企业日常经营中&#xff0c;快速上传和下载文件至关重要。然而&#xff0c;在使用FTP&#xff08;文件传输协议&#xff09;进行文件传输时&#xff0c;速度可能成为瓶颈。为了提升工作效率&#xff0c;以下是一些建议&#xff0c;可以帮助企业提高FTP上传下载速度。 1、确保…