【深入理解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。这两个类是字节流最常用的实现类之一。

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

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

相关文章

【SERVERLESS】腾讯云上实操

我们先来看看 云计算的 发展 流程 虚拟化的云计算方式: IaaS基础设施即服务【邮箱、微信、支付宝等】PaaS平台即服务【数据库服务、大数据计算平台】Saas软件即服务【云服务器、cpu、硬盘】 早期我们可能只听过上面这三个词 ,但是随着云计算的发展,新…

HIS系统是什么?一套前后端分离云HIS系统源码 接口技术RESTful API + WebSocket + WebService

HIS系统是什么?一套前后端分离云HIS系统源码 接口技术RESTful API WebSocket WebService 医院管理信息系统(全称为Hospital Information System)即HIS系统。 常规模版包括门诊管理、住院管理、药房管理、药库管理、院长查询、电子处方、物资管理、媒体管理等&…

javaWeb车辆管理系统设计与实现

摘 要 随着经济的日益增长,车辆作为最重要的交通工具,在企事业单位中得以普及,单位的车辆数目已经远远不止简单的几辆,与此同时就产生了车辆资源的合理分配使用问题。 企业车辆管理系统运用现代化的计算机管理手段,不但可以对车辆的使用进行合理的管理,…

Pentaho Data Integration(kettle)下载

Kettle已然是改了名了,新名字叫Pentaho Data Integration 网上常见的下载地址已经失效,被提示找不到Date Integration目录: https://sourceforge.net/projects/pentaho/files/Data%20Integration/ 点击页面上的pdf,下载文件后打…

JavaScript的函数基础

目录 前言: 1.函数是什么: 2.函数的基本使用: 2.1 定义函数: 2.2. 调用函数 2.3函数命名规范: 2.3.1由数字、字母、下划线组成: 2.3.2区分大小写: 2.3.3不能数字开头,也不能是关键字: 2.3.4自定义函数纯小写&#xff1a…

YOLOV8注意力改进方法:Deformable Attention Transformer(附改进代码)

原论文地址:原论文下载地址 论文摘要:Transformer最近在各种视觉任务上表现出了优异的性能。对于巨大的甚至是全局性的感受野赋予Transformer模型比CNN模型更高的表现力。然而,仅仅扩大感受野也会引起一些担忧。一方面,在ViT中使…

01 华为华三模拟器解决兼容问题

01 华为华三模拟器解决兼容问题 AI思路 要让华为和华三的模拟器兼容,您可以尝试以下方法: 更新模拟器版本:确保您使用的华为和华三模拟器都是最新版本。在华为官方网站或华三官方网站上下载最新的模拟器版本。 检查系统要求:确保…

Java调试之JDB命令行调试入门

0.前言 Java 调试器 (JDB) 是一个简单的 Java 类命令行调试器。 jdb 命令及其选项调用 JDB。 jdb 命令演示了 Java 平台调试器架构,并提供本地或远程 JVM 的检查和调试。 1.准备待调试的Java应用程序 public class JDB {public static int sum(int a,int b){int …

【简单讲解下PHP AES加解密示例】

🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…

[C++][算法基础]合并集合(并查集)

一共有 n 个数,编号是 1∼n,最开始每个数各自在一个集合中。 现在要进行 m 个操作,操作共有两种: M a b,将编号为 a 和 b 的两个数所在的集合合并,如果两个数已经在同一个集合中,则忽略这个操…

如何恢复被.locked勒索病毒加密的服务器和数据库?

.locked勒索病毒有什么特点? .locked勒索病毒的特点主要包括以下几个方面: 文件加密:.locked勒索病毒会对受感染设备上的所有文件进行加密,包括图片、文档、视频和其他各种类型的重要文件。一旦文件被加密,文件的扩展…

指针的深入理解(六)

指针的深入理解(六) 个人主页:大白的编程日记 感谢遇见,我们一起学习进步! 文章目录 指针的深入理解(六)前言一. sizeof和strlen1.1sizeof1.2strlen1.3sizeof和strlen对比 二.数组名和指针加减…