IO流(IO Stream)

一、概述

我们已经系统学习了File 类,并且已经知道 File 类的实例用于表示文件或目录的路径
名。

虽然我们可以通过 File 实例来访问文件或目录的元数据,甚至可以创建、删除文件或目
录,但是,我们却不能通过File实例来访问文件中存储的内容,本节主要研究通过流来
读写数据。

为了能够 读取文件中的内容 或者 向文件中写入内容 ,就需要用到文件输入流或文件输
出流,本节将系统讲解通过流完成对文件内容的读取和写入操作。

但千万不要认为我们只能从文件中读取数据或向文件中写入数据,还有在之前我们从控制
台获取或打印到控制台以及在网络编程部分我们将会学习如何通过 Java 程序从网络
上读取数据和向网络发送数据。

1.流

Java 语言中,将够 读取数据 或者 写出数据 的对象抽象为 流。

流 类似于生活当中的 水管 , 水 可以在 水管 中 定向移动 ,正如 数据 可以在 流 中定向移
动。

我们把这种数据的传输,可以看做是一种数据的流动,按照流动的方向,以内存为基准,
分为 输入input和 输出 output ,即流向内存是输入流,流出内存是输出流。

JavaI/O操作主要是指使用java.io包下的内容,进行输入、输出操作。输入也叫做读
取数据,输出也叫做作写出数据。

Java 传统的IO体系中,所有的 流 对应的类型都扩展自四个抽象类:

其中的 InputStream OutputStream 的子类表示字节流, ReaderWriter的子类则
表示字符流。

这里所提及的Stream一词均表示流,请不要与 java.util.stream.Stream 接口混为
一谈。

2.分类

Java中传统的I/O体系可以按照不同的方式对流进行分类:

  • 按照流中数据的流向来分类,可以分为 输入流 和 输出流
    - 用于实现从外部读取数据到当前程序的流被称作输入流
    - 用于实现从当前程序中向外部输出数据的流被称作输出流
  • 按照流处理的数据单元来分类,可以划分为 字节流 和 字符流
    - 如果某个流在读取或写入数据时以字节为单位,则该流属于字节流
    - 如果某个流在读取或写入数据时以字符为单位,则该流属于字符流
    - 这里纠正一下个错误,通过字符流读写字符数据时,一个字符未必就占两个字节
    - 一个字符有可能是1个字节,也可能是2个、3个、4个字节,这取决于字符编码
  • 按照流的功能来分类,可以分为 节点流 和 包装流
    - 直接数据节点中读取数据或向数据节点中写入数据的流被称作节点流
    - 数据节点可以是磁盘上的文件或其它数据源(比如键盘输入)
    - 节点流都比较原始,仅用于实现数据的读取和写入,通常不具备其它功能
    - 用于从其它流中读取数据,并实现其它流所不具备的功能的流,被称作包装流
    - 包装流也被称作 转换流 或 处理流 或 过滤流
    - 包装流通常会提供它内部所包装的流不具备的功能
    - 包装流内部所处理的流(也称作所过滤的流)被称作底层支持流
    节点流 和 包装流 的关系如下图所示:
    在这里插入图片描述

3.一切皆字节

一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都是一个一
个的字节,那么传输时一样如此。所以,字节流可以传输任意文件数据。在操作流的时
候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据。

二、字节流

字节流 是以 字节 为单位读写数据的输入流或输出流。下图是Java语言中提供的 字节流
的继承体系:
在这里插入图片描述
由图可以看到, 字节流 体系中涉及的类太多,我们仅选择具有代表性的几个予以讲解,
并不是全部讲解。

1.Closeable

​java.io.Closeable 接口,实现此接口的都是可以关闭的数据的源或目的地。都会实现 c lose() 方法。如: Scanner , InputStream , OutputStream

public interface Closeable extends AutoCloseable

该类继承了 java.lang.AutoCloseable AutoCloseable 接口提供了自动关闭的能力。

2.字节输入流

2.1 InputStream

InputStream 类是所有表示字节输入流的类的父类,它是个抽象类,因此不能直接被实例
化。

public abstract class InputStream implements Closeable

InputStream 类是所有字节输入流的最顶层父类,掌握该类的使用即可从根本上把握其它
字节输入流的使用。
在这里插入图片描述

2.1.1 构造方法

InputStream 类仅有一个无参构造供子类调用:

public InputStream()

2.1.2 实例方法

在这里插入图片描述
JDK9 提供的方法:
transferTo(OutputStream out) 用于将输入流使用指定的输出流输出出去

public long transferTo(OutputStream out) throws IOException {
Objects.requireNonNull(out, "out");
long transferred = 0;
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int read;
while ((read = this.read(buffer, 0, DEFAULT_BUFFER_SIZE)) >= 0) {
out.write(buffer, 0, read);
transferred += read;
}
return transferred;
}

复制文件:

package file;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;public class Demo07_0912 {public static void main(String[] args) {/*** 将 F:\temp\test.mp4可 复制到 D:\kaifamiao\software\text\test.mp4* 使用`transferTo()`,将输入流的内容直接写入输出流*/try {FileInputStream fis = new FileInputStream("F:\\test.mp4");FileOutputStream fos = new FileOutputStream("D:\\kaifamiao\\software\\text\\test.mp4");//第一种方法
//            byte[] bytes = new byte[8019];
//            int size;
//            while ((size=fis.read(bytes))!=-1){
//                fos.write(bytes,0,size);
//            }//            //第二种方法
//            byte[] bytes = fis.readAllBytes();
//            fos.write(bytes);//第三种方法fis.transferTo(fos);fis.close();fos.close();} catch (FileNotFoundException e) {throw new RuntimeException(e);} catch (IOException e) {throw new RuntimeException(e);}}
}

readAllBytes()读取所有的字节(最大为 Integer.MAX_VALUE 个字节)

public byte[] readAllBytes() throws IOException {
return readNBytes(Integer.MAX_VALUE);
}

在所有方法中,仅 read() 方法是抽象方法,因此 InputStream 类的所有的子类都需要
实现该方法。
因为 InputStream 类是个抽象类,因此必须借助于其 非抽象子类 来完成实例化。
主要学习 FileInputStreamBufferedInputStream

2.2FileInputStream

FileInputStream 用于从文件系统中的某个文件中读取内容(以字节为单位)。
FileInputStream 用于读取诸如图像数据之类的原始字节流。
如需读取字符流,可以考虑使用 InputStreamReaderFileReader

public class FileInputStream extends InputStream

2.2.1 构造方法

FileInputStream 类中定义了三个公开( public )的构造方法:
在这里插入图片描述
其中较为常用的是前两个构造方法。

package com.itlaobing.demo.stream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Test {
public static void main(String[] args) throws FileNotFoundException {
FileInputStream in = new FileInputStream("D:\\temp\\zixiafaerie.jpg");
File file = new File("D:\\temp\\zixiafaerie.jpg");
FileInputStream input = new FileInputStream(file);
}
}

2.2.2 实例方法

FileInputStream 类重写了 InputStream 类中所有的 public 方法,但除了以下方法未被重写外,其它方法均已被 FileInputStream 类所重写

public void reset() throws IOException
public void mark(int readlimit) throws IOException
public boolean markSupported() throws IOException

重写的方法包括:

public int available() throws IOException
public int read() throws IOException
public int read(byte[] bytes) throws IOException
public int read(byte[] bytes, int offset, int length) throws IOException
public long skip(long n) throws IOException
public void close() throws IOException

这里仅结合 FileInputStream 来讲解 InputStream 类中的核心方法的用法。

首先,我们创建在D:/temp目录下创建一个名称为file-input.txt的文件,其中内容如
下:

abcd1234efg
我和我的祖国
A little cold awn first, then gun out such as dragon.

然后我们分别用三种不同的方式读取该文件( D:/temp/file-input.txt )中的数据。
这里需要注意,直接在 Windows 系统中创建的 文本文档 ,其默认编码为 GBK (每个汉字
占用两个字节)。

2.2.3读取单个字节

InputStream类中定义的抽象方法是所有子类所必须实现的:

public abstract int read() throws IOException

该方法用于从字节输入流中读取单个字节;如果到达流的末尾,则返回 -1 。
而另一个方法 skip 则用于跳过指定的字节数:

public long skip(long n) throws IOException

该方法的参数 n 表示期望跳过的字节数,而返回值则表示实际所跳过的字节数。
同时, InputStream 类提供了获取流中剩余字节数的方法:

public int available() throws IOException

用于获取可以不受阻塞地从此输入流读取(或跳过)的估计字节数;如果到达输入流末
尾,则返回 0 。

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

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

相关文章

春秋云镜 CVE-2015-1427

春秋云镜 CVE-2015-1427 ElasticSearch RCE 靶标介绍 ElasticSearch RCE 启动场景 漏洞利用 因查询时至少要求es中有一条数据,所以发送如下数据包,增加一个数据: POST /website/blog/ HTTP/1.1 Host: eci-2zedttamjkr80i9iubel.cloudeci…

Linux安装MySQL8.0

又又又又..Linux装MySQL。 删除原有的MySQL 查看安装的mysql信息:rpm -qa|grep -i mysql 删除mysql相关服务:rpm -e --nodeps 查询mysql遗留文件和依赖信息:find / -name mysql 手动删除mysql配置文件:rm -rf /etc/my.cnf 相关…

MySQL锁

MySQL锁 事务事务的隔离级别脏读,不可重复读,幻读 表锁与行锁表锁测试准备测试 行锁测试 读锁与写锁读锁(共享锁)测试 写锁(排他锁)测试 元数据锁表级元数据锁表级MDL**(Metadata Lock&#xff…

十大排序算法及Java中的排序算法

文章目录 一、简介二、时间复杂度三、非线性时间比较类排序冒泡排序(Bubble Sort)排序过程代码实现步骤拆解演示复杂度 选择排序(Selection Sort)排序过程代码实现步骤拆解演示复杂度 插入排序(Insertion Sort&#xf…

【Linux常用命令】

一、防火墙相关 1、查看防火墙状态 systemctl status flrewalld2、如果防火墙是开启状态的,需要关闭 systemctl stop firewalld3、永久行关闭操作(禁止开机自启动) 因为防火默认是开启状态的,如果只是手动关闭,先次…

【Java】抽奖系统———保姆学习教程

目录 一、抽奖系统介绍 二、代码实现 1、随机生成中奖号码 1.1、中奖号码createNumber方法 1.2、控制判断contains方法 2、用户输入中奖号码 3、判断中奖情况 3.1、判断奖项isWin方法 三、完整代码 一、抽奖系统介绍 抽奖的号码由6个红色球号码和1个蓝色球号码组成。红色…

智慧园区:AI边缘计算技术与视频监控汇聚平台打造智慧园区解决方案

一、行业趋势与背景 智慧园区是现代城市发展的重要组成部分,通过智能化技术提高园区的运营效率、降低成本、增强环境可持续性等具有重要作用。在智慧园区中,人工智能和视频汇聚技术是重要的前置技术。人工智能技术可以实现对数据的智能化处理和分析&…

时序数据库 TimescaleDB 安装与使用

TimescaleDB 是一个时间序列数据库,建立在 PostgreSQL 之上。然而,不仅如此,它还是时间序列的关系数据库。使用 TimescaleDB 的开发人员将受益于专门构建的时间序列数据库以及经典的关系数据库 (PostgreSQL),所有这些都具有完整的…

2023/9/13 -- C++/QT

作业&#xff1a; 1> 将之前定义的栈类和队列类都实现成模板类 栈&#xff1a; #include <iostream> #define MAX 40 using namespace std;template <typename T> class Stack{ private:T *data;int top; public:Stack();~Stack();Stack(const Stack &ot…

TouchGFX之缓存位图

位图缓存是专用RAM缓冲区&#xff0c;应用可将位图保存&#xff08;或缓存&#xff09;在其中。 如果缓存了位图&#xff0c;在绘制位图时&#xff0c;TouchGFX将自动使用RAM缓存作为像素来源。位图缓存在许多情况下十分有用。 从RAM读取数据通常比从闪存读取要快&#xff08;特…

Linux下Minio分布式存储安装配置(图文详细)

文章目录 Linux下Minio分布式存储安装配置(图文详细)1 资源准备1.1 创建存储目录1.2 获取Minio Server资源1.3 获取Minio Client资源 2 Minio Server安装配置2.1 切换目录2.2 后台启动2.3 查看进程2.4 控制台测试 3 Minio Client安装配置3.1 切换目录3.2 移动mc脚本3.2 运行mc命…

Vue3后台管理系统Element-plus_侧边栏制作_无限递归

在home.view中添加代码 <template><div><div class"common-layout"><el-container><el-header class"common-header flex-float"><div class"flex"><img class"logo" src"../assets/logo…

【Redis】Redis实现分布式锁

【Redis】Redis常见面试题&#xff08;1&#xff09; 文章目录 【Redis】Redis常见面试题&#xff08;1&#xff09;1. 为什么要用分布式锁2. Redis如何实现分布式锁3. Redis接受多个请求模拟演示4. 使用Redis实现分布式锁会存在什么问题4.1 一个锁被长时间占用4.2 锁误删 【Re…

vue2+element-ui批量导入方法并判断上传的文件是否为xls或xlsx

业务需求: 代码结构: <el-dialogtitle"批量导入":close-on-click-modal"true"close"close()":visible"true"width"35%":center"true"><div class"el-dialog-div"><!-- 头部区域布局 -…

【基本数据结构 四】线性数据结构:队列

学习了栈后,再来看看第四种线性表结构,也就是队列,队列和栈一样也是一种受限的线性表结构,和栈后进先出的操作方式不同的是,队列是FIFO的结构,也就是先进先出的操作方式。 队列的定义 队列这个概念非常好理解。可以把它想象成排队买票,先来的先买,后来的人只能站末尾…

软考知识汇总--结构化开发方法

文章目录 1 结构化开发2 耦合3 内聚4 设计原则5 系统文档6 数据流图6.1 数据流图的基本图形元素 7 数据字典 1 结构化开发 结构化方法总的指导思想是自顶向下、逐层分解&#xff0c;它的基本原则是功能的分解与抽象。它是软件工程中最早出现的开发方法&#xff0c;特别适合于数…

「C++程序设计 (面向对象进阶)」学习笔记・二

0、引言 本专栏的系列文章是在学习 北京邮电大学 崔毅东 老师的《C程序设计 (面向对象进阶)》课程过程中整理的。欢迎前往专栏了解更多相关内容~ &#x1f600; 有关于现代 C 的基本介绍&#xff0c;请前往《现代C基本介绍》&#xff01; &#x1f514; 先决条件 本专栏的系列…

定时器+BOM

9.定时器BOM 1.定时器 **概念:**重复执行一个函数 1.1setInterval() setInterval(“代码/函数”,时间,参数),返回定时器的序列号,默认从1开始 clearInterval(序列号)清除定时 <button class"start">开启定时器</button><button class"close…

通过Power Platform自定义D365 CE 业务需求 - 3. 使用Microsoft Power应用程序

Microsoft Power Apps是一个用于开发应用程序的无代码、无代码平台。Power应用程序可以在Dataverse之上配置为数据库。尽管您可以连接Salesforce、OneDrive、Dropbox等多种云源,但Dataverse也可以用作内部数据库来构建应用程序,并通过连接器连接其他数据源进行集成。 Power应…

Java开发之Redis核心内容【面试篇 完结版】

文章目录 前言一、redis使用场景1. 知识分布2. 缓存穿透① 问题引入② 举例说明③ 解决方案④ 实战面试 3. 缓存击穿① 问题引入② 举例说明③ 解决方案④ 实战面试 4. 缓存雪崩① 问题引入② 举例说明③ 解决方案④ 实战面试 5. 缓存-双写一致性① 问题引入② 举例说明③ 解决…