【深入理解Java IO流0x03】解读Java最基本的IO流之字节流InputStream、OutputStream

在开始前,我们再来回顾一下这张图:
image.png
本篇博客主要为大家讲解字节流。
我们都知道,一切文件(文本、视频、图片)的数据都是以二进制的形式存储的,传输时也是。所以,字节流可以传输任意类型的文件数据

1. 字节输入流InputStream

java.io.InputStream是字节输入流的超类。来看一下它的抽象方法:

  • close() :关闭此输入流并释放与此流相关的系统资源。
  • int read(): 从输入流读取数据的下一个字节。
  • read(byte[] b): 该方法返回的 int 值代表的是读取了多少个字节,读到几个返回几个,读取不到返回-1
  • available():返回输入流中可以读取的字节数

2. 字节输入流FileInputStream

InputStream有很多子类,FileInputStream就是实现子类中最简单的一个。看名字就知道是文件输入流,用于将数据从文件中读取数据。

2.1 构造方法

  • FileInputStream(String name):创建一个 FileInputStream 对象,并打开指定名称的文件进行读取。文件名由 name 参数指定。如果文件不存在,将会抛出 FileNotFoundException 异常。
  • FileInputStream(File file):创建一个 FileInputStream 对象,并打开指定的 File 对象表示的文件进行读取。

实战一下:

@Test
public void test005() throws IOException {
    FileInputStream fis = new FileInputStream("test.txt");
    
    int data;
    while((data=fis.read())!=-1){
        System.out.println((char)data);
    }
    fis.close();
}

2.2 常用方法

一、读取字节
read()方法会读取一个字节并且返回其正数表示,如果到达文件末尾,返回-1。读取时发生错误会抛IOException异常。
实战代码:

@Test
public void test005() throws IOException {
    FileInputStream fis = new FileInputStream("test.txt");
    
    int data;
    while((data=fis.read())!=-1){
        System.out.println((char)data);
    }
    fis.close();
}

二、读取字节数组
read(byte[] b)方法会从输入流中最多读取b.length个字节,并将它们存储到缓冲区数组 b 中。
实战代码:

@Test
public void test005() throws IOException {
    File file = new File("test.txt");
    FileInputStream fis = new FileInputStream(file);
    byte[] buf = new byte[1024];
    int count;
    while((count=fis.read(buf))!=-1){
        System.out.println(new String(buf,0,count));
    }
    fis.close();
}

3. 字节输出流OutputStream

java.io.OutputStream是字节输出流的超类。来看一下它的抽象方法:

  • close():关闭此输出流并释放与此流相关联的系统资源。
  • flush():刷新此输出流并强制缓冲区的字节被写入到目的地。
  • write(byte[] b):将 b.length 个字节从指定的字节数组写入此输出流。
  • write(byte[] b, int off, int len):从指定的字节数组写入 len 字节到此输出流,从偏移量 off开始。 也就是说从off个字节数开始一直到len个字节结束。

4. 字节输出流FileOutputStream

OutputStream有很多子类,最简单的一个子类就是 FileOutputStream 。看名字就知道是文件输出流,用于将数据写入到文件。

4.1 构造方法

  • FileOutputStream(String name):创建一个 FileOutputStream 对象,并打开指定名称的文件进行写入。文件名由 name 参数指定。如果文件不存在,则创建一个新文件;如果文件已经存在,则覆盖原有文件
  • FileOutputStream(String name, boolean append):参数append表示是否为"追加"模式,默认为false不追加也就是清空原有数据。
  • FileOutputStream(File file):创建一个 FileOutputStream 对象,并打开指定的 File 对象表示的文件进行写入。

实战一把:

@Test
public void test006() {
    FileOutputStream fos = null;
    try {
        fos = new FileOutputStream("test2.txt");
        fos.write("i love cola.你好世界!".getBytes());
    } catch (IOException e) {
        throw new RuntimeException(e);
    } finally {
        try {
            fos.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

4.2 常用方法

一、写入字节
write(int b) 方法,每次可以写入一个字节,代码如下:

// 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream("fos.txt");     
// 写出数据
fos.write(97); // 第1个字节,等效于'a'  因为a的ASCII码为97
fos.write(98); // 第2个字节
fos.write(99); // 第3个字节
// 关闭资源
fos.close();

当使用 write(int b) 方法写出一个字节时,参数 b 表示要写出的字节的整数值。由于一个字节只有8位,因此参数 b 的取值范围应该在 0 到 255 之间,超出这个范围的值将会被截断。例如,如果参数 b 的值为 -1,那么它会被截断为 255,如果参数 b 的值为 256,那么它会被截断为 0。
在将参数 b 写入输出流中时,write(int b) 方法只会将参数 b 的低8位写入,而忽略高24位。这是因为在 Java 中,整型类型(包括 byte、short、int、long)在内存中以二进制补码形式表示。当将一个整型值传递给 write(int b) 方法时,方法会将该值转换为 byte 类型,只保留二进制补码的低8位,而忽略高24位。
例如,如果要写出的整数为 0x12345678,它的二进制补码表示为 0001 0010 0011 0100 0101 0110 0111 1000。当使用 write(int b) 方法写出该整数时,只会将二进制补码的低8位 0111 1000 写出,而忽略高24位 0001 0010 0011 0100 0101 0110。这就是参数 b 的高24位被忽略的原因。
0111 1000 是一个8位的二进制数,它对应的十进制数是 120,对应的 ASCII 码字符是小写字母 “x”。在 ASCII 码表中,小写字母 “x” 的十进制 ASCII 码值为 120。因此,如果使用 write(int b) 方法写出一个字节值为 0x78(十进制为 120),那么写出的结果就是小写字母 “x”。
验证一下:

FileOutputStream fos = null;
try {
    fos = new FileOutputStream("example.txt");

    fos.write(120);
    fos.write('x');
    fos.write(0x12345678);
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (fos != null) {
        try {
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

最终文本中:
image.png
二、写入字节数组
write(byte[] b),代码示例:

// 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream("fos.txt");     
// 字符串转换为字节数组
byte[] b = "你好世界~Hello World".getBytes();
// 写入字节数组数据
fos.write(b);
// 关闭资源
fos.close();

另外再补充一下,在 Windows 系统中,换行符号是\r\n,而在Linux系统中换行则是\n

5. 字节流实战

实战环节,要求通过字节流复制图片。
实现很简单,就是通过字节输入流读取图片,再用字节输出流输出到指定位置即可。

@Test
public void test007() throws IOException{
    FileInputStream fis = new FileInputStream("snoopy.png");
    FileOutputStream fos = new FileOutputStream("snoopy_copy.png");

    byte[] buf = new byte[1024];
    int count=0;
    while((count=fis.read(buf))!=-1){
        fos.write(buf,0,count);
    }
    fis.close();
    fos.close();
}

上面的代码创建了一个 FileInputStream 对象以读取原始图片文件,并创建了一个 FileOutputStream 对象以写入复制后的图片文件。然后,使用 while 循环逐个读取原始图片文件中的字节,并将其写入复制后的图片文件中。最后,关闭输入流和输出流释放资源。

6. 小结

InputStream是字节输入流的抽象类,它定义了读取字节数据的方法,如read()read(byte[] b)read(byte[] b, int off, int len)等。OutputStream是字节输出流的抽象类,它定义了写入字节数据的方法,如 write(int b)write(byte[] b)write(byte[] b, int off, int len) 等。这两个抽象类是字节流的基础。
FileInputStream是从文件中读取字节数据的流,它继承自InputStreamFileOutputStream是将字节数据写入文件的流,它继承自OutputStream。这两个类是字节流最常用的实现类之一。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构】复杂度(长期维护)

本篇博客主要是浅谈数据结构概念及时间复杂度,并做长期的维护更新,有需要借鉴即可。 复杂度目录 一、初识数据结构1.基础概念2.如何学好数据结构 二、复杂度1.复杂度2.时间复杂度①有限数的时间复杂度②函数的时间复杂度③二分查找时间复杂度④递归拓展练…

转让名称带中国的金融控股集团公司要多少钱

随着公司的发展和市场竞争的影响,越来越多的创业者希望注册一家好名称的公司,以提高企业知名度和竞争力。但是,注册中字头无地域公司需要满足一定的条件和流程。本文将对中字头无地域公司注册条件及流程进行详细的介绍。可以致电咨询我或者来…

动态支付策略:Go 语言中策略模式的妙用

关注公众号【爱发白日梦的后端】分享技术干货、读书笔记、开源项目、实战经验、高效开发工具等,您的关注将是我的更新动力! 在现代软件架构中,支付功能是不可或缺的一环。无论是在线购物还是虚拟服务,支付策略的选择直接影响用户体…

transform 模型常见问题

目录 transform 模型常见问题 transform 模型常见问题 1.Transformer为何使用多头注意力机制?(为什么不使用一个头) 答:多头可以使参数矩阵形成多个子空间,矩阵整体的size不变,只是改变了每个head对应的维度大小,这样做使矩阵对多方面信息进行学习,但是计算量和单个h…

JWT/JWS/JWE

JWT(JSON Web Token):一种基于JSON格式,用于在Web应用中安全传递用户身份验证和授权信息的标准令牌,可以包含签名(JWS)和加密(JWE)的信息 MacAlgorithm(Message Authentication Code Algorithm):消息认证码算法 HMAC(Hash-based…

【C++】详解 Unique 函数 (小白一看就懂!!!)

目录 一、前言 二、去重函数 Unique() ✨头文件 ✨用法与作用 ✨注意点 三、常考面试题 四、共勉 一、前言 经常刷算法题的朋友,肯定会经常看到题目中提到 去重 这样的字眼,或者需要我们通过 去重 来解题,由于之前对 去重 了解的不太清楚…

2024/4/1—力扣—删除字符使频率相同

代码实现: 思路: 步骤一:统计各字母出现频率 步骤二:频率从高到低排序,形成频率数组 步骤三:频率数组只有如下组合符合要求: 1, 0...0n 1, n...n (, 0)n...n, 1(, 0) bool equalFrequency(char…

【C++学习】哈希的应用—位图与布隆过滤器

目录 1.位图1.1位图的概念1.2位图的实现3.位图的应用 2.布隆过滤器2.1 布隆过滤器提出2.2布隆过滤器概念2.3如何选择哈希函数个数和布隆过滤器长度2.4布隆过滤器的实现2.4.1布隆过滤器插入操作2.4.2布隆过滤器查找操作2.4.3 布隆过滤器删除 2.5 布隆过滤器优点2.6布隆过滤器缺陷…

UE4_动画基础_角色的缩放

以第三人称模板进行制作。 一、首先为角色缩放新建粒子效果 1、新建niagara system,重命名为NS_Shrink。 2、双击打开设置参数: 发射器重命名: Emitter State: 发射器一次喷发数量: 粒子初始大小,生命周…

PANet网络

PANet(Path Aggregation Network)是一种用于语义分割任务的神经网络结构,旨在解决多尺度特征融合的问题。该网络结构由中国科学院计算技术研究所提出,在2018年的论文中首次提出。 PANet的主要目标是解决语义分割任务中多尺度信息…

第8章 数据集成和互操作

思维导图 8.1 引言 数据集成和互操作(DII)描述了数据在不同数据存储、应用程序和组织这三者内部和之间进行移动和整合的相关过程。数据集成是将数据整合成物理的或虚拟的一致格式。数据互操作是多个系统之间进行通信的能力。数据集成和互操作的解决方案提供了大多数组织所依赖的…

Oracle 常用SQL命令

Oracle 常用SQL命令 1、备份单张表 创建复制表结构 create table employeesbak as select * from cims.employees 如果只复制表结构,只需要在结尾加上 where 10 插入数据 insert into employeesbak select * from cims.employees 删除一条…

阿里开源Qwen-1.5-32B模型,性能超Mixtral MoE

简介 开源社区长期以来一直在寻求一种能在性能、效率和内存占用之间达到理想平衡的模型。尽管出现了诸如Qwen1.5-72B和DBRX这样的SOTA模型,但这些模型持续面临诸如内存消耗巨大、推理速度缓慢以及显著的微调成本等问题。当前,参数量约30B的模型往往在这…

day75 js 正则表达式 window对象轮播图片调用定时器

一 正则表达式: RegExp 对象: 对字符串执行模式匹配的强大工具。 1 创建正则表达式对象 let reg /模式/修饰符 修饰符 attributes 是一个可选的字符串,包含属性 "g"、"i" 和 "m", …

2024 年广东省职业院校技能大赛(高职组)“云计算应用”赛项样题 5

#需要资源(软件包及镜像)或有问题的,可私聊博主!!! #需要资源(软件包及镜像)或有问题的,可私聊博主!!! #需要资源(软件包…

八次危机笔记

文章目录 前言一、思维导图危机一危机二危机三危机四危机五危机六危机七危机八 前言 重塑三观,致敬温老。一个有良心的学者!!! 一、思维导图 危机一 危机二 危机三 危机四 危机五 危机六 危机七 危机八 ☆

2024年最新可用免费云服务器整理汇总

随着云计算技术的不断发展,越来越多的个人和企业开始使用云服务器来满足其数据存储、网站搭建、应用开发等需求。其中,免费云服务器更是受到广大用户的青睐。本文将为大家整理汇总最新的可用免费云服务器资源,助力大家轻松享受云上之旅&#…

LinkedHashMap 集合源码分析

LinkedHashMap 集合源码分析 文章目录 LinkedHashMap 集合源码分析一、字段分析二、内部类分析三、构造方法分析四、内部方法分析五、总结 LinkedHashMap 是 HashMap 的子类,在 HashMap 的基础上维护了双向链表,保证了有序性。默认是不排序的&#xff0c…

ATAM方法架构评估实践

用ATAM方法评估软件体系结构,其工作分为4个基本阶段,即演示、调查和分析、测试和报告ATAM(如图1所示)。接下来分别就每个阶段的实践进行详细介绍。 图1 ATAM方法的评估实践阶段划分 1.阶段1——演示(Presentation&…

【Linux进阶之路】地址篇

文章目录 一、ipv4地址1. 基本概念2. 分类3.CIDR4.特殊的ip地址 二、IP协议1. 协议字段2.分片与重组3.路由 三、NAT技术1.公有和私有2.NAT3.NAPT 四、ARP协议1.MAC地址2.ARP 五、DHCP协议六、DNS协议尾序 一、ipv4地址 1. 基本概念 概念:IP地址,英文全…