【Java面向对象】二进制I/O

news2024/12/24 9:16:02

文章目录

  • 1.二进制文件
  • 2.二进制 I/O 类
    • 2.1 FileInputStream 和 FileOutputStream
    • 2.2 FilterInputStream和 FilterOutputStream
    • 2.3 DatalnputStream 和 DataOutputStream
    • 2.4 BufferedInputStream 和 BufferedOutputStream
    • 2.5 ObjectInputStream 和 ObjectOutputStream
  • 2.6 Serializable接口
    • 2.7 序列化数组
  • 3.随机访问文件

1.二进制文件

文件可以分为文本或者二进制的。可以使用文本编辑器,比如 Windows 下的记事本或者 UNIX 下的 vi 编辑器,进行处理(读取、创建或者修改)的文件称为文本文件。所有其他的文件称为二进制文件。
不能使用文本编辑器来读取二进制文件一它们被设计为使用程序来读取。例如,Java 源程序存储在文本文件中,可以使用文本编辑器读取,而 Java 类文件是二进制文件,由 Java 虚拟机读取。

计算机并不区分二进制文件和文本文件。所有的文件都是以二进制形式来存储的,因此,从本质上说,所有的文件都是二进制文件。文本 I/O 建立在二进制 I/O 的基础之上,它能提供一层抽象,用于字符的编码和解码。
对于文本I/O,编码和解码是自动进行的。在写入字符时,Java 虚拟机会将 Unicode 码转化为文件特定的编码,而在读取字符时,将文件特定的编码转化为 Unicode 码。
二进制 I/O 不需要转化。如果使用二进制 I/O 向 文件写入一个数值,就是将内存中的那个值复制到文件中。
由于二进制 I/O 不需要编码和解码,所以,它比文本 I/O 效率高。二进制文件与主机的编码方案无关,因此,它是可移植的。任何机器上的 Java 程序都可以读取 Java 程序所创建的二进制文件。这就是为什么 Java 的类文件存储为二进制文件的原因。Java 类文件可以在任何具有 Java 虚拟机的机器上运行。

一般来说,对于文本编辑器或文本输出程序创建的文件,应该使用文本输入来读取,对于 Java 二进制输出程序创建的文件,应该使用二进制输入来读取。

2.二进制 I/O 类

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.1 FileInputStream 和 FileOutputStream

几乎所有的 I/O 类中的方法都会抛出异常java.io.IOException。因此,必须在方法中声明会抛出java.io.工OException异常,或者将代码放到 try-catch 块中。

import java.oi.*;
public class TestFileStream{
	public static void main(String[] args){
		try{
			FileOutputStream output = new FileOutputStream("temp.txt");
		}{
			for(int i = 0;i<10;i++)
				output.write(i);
		}

		try{
			FileInputStream input = new FileInputStream("temp.txt");
		}{
		int value;
		while((value=input.read())!=1)
			System.out.print(value + " ");
		}	
	}
}

2.2 FilterInputStream和 FilterOutputStream

过滤器数据流 ( filterstream) 是为某种目的过滤字节的数据流。基本字节输入流提供的读取方法 read 只能用来读取字节。
如果要读取整数值、双精度值或字符串,那就需要一个过滤器类来包装字节输入流。使用过滤器类就可以读取整数值、双精度值和字符串,而不是
字节或字符。
FilterlnputStream 类和 FilterOutputStream 类是用于过滤数据的基类。需要处理基本数值类型时,就使用 DatalnputStream 类和 DataOutputStream 类来过滤字节。

2.3 DatalnputStream 和 DataOutputStream

DatalnputStream 从数据流读取字节,并且将它们转换为合适的基本类型值或字符串。
DatabutputStream 将基本类型的值或字符串转换为字节, 并且将字节输出到流。
在这里插入图片描述
在这里插入图片描述
如果到达 Inputstream 的末尾之后还继续从中读取数据,就会产生 EOFException 异常。这个异常可以用来检查是否已经到达文件末尾。

import java.io.*;
public class Write{
	public static void main(String[] args){
		try{
			try(new DataOutputStream(new FileOutputStream("test.dat"))){
				output.writeDouble(4.5);
			}
			try(DatalnputStream input =new DataInputStream(new Fi1eInputStream("test .dat"))){
				while(true)
					System.out.println(input.readDouble());
			}
		}
		catch(EOFException ex){
			System.out.println("All data were read");
		}
		catch(IOException ex){
			ex.printStackTrace();
		}
	}
}

2.4 BufferedInputStream 和 BufferedOutputStream

BufferedlnputStream 类和 BufferedOutputStream 类可以通过减少磁盘读写次数来提高输入和输出的速度。使用 BufferdlnputStream 时,磁盘上的整块数据一次性地读入内存的缓冲区中。然后从缓冲区中将单个数据传递到程序中。

DataOutputStream output = new DataOutputStream(
	new BufferedOutputStream (new FileOutputStream("temp.dat"))) ;
DatalnputStream input = new DataInputStream(
	new BufferedInputStream(new FileInputStream("temp.dat")))

2.5 ObjectInputStream 和 ObjectOutputStream

DatalnputStream 类和 DataOutputStream 类可以实现基本数据类型与字符串的输入和输出。而 ObjectlnputStream 类和 ObjectOutputStream 类除了可以 实现基本数据 类型与字符串的输入 和输出之外,还可以实现对象的输入和输出。
由于 ObjectlnputStream 类和ObjectOutputStream 类包含 DatalnputStream 类 和 DataOutputStream 类 的所有 功能,所以,完全可以用 ObjectInputStream 类和 ObjectOutputStream 类代替 DatalnputStream 类和DataOutputStream类。

import java.io.*;
public class Test{
	public static void main(String[] args)
		throws IOException{
		try{
			ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("o.dat"));
			// 可以改为
			// ObjectOutputStream output = new ObjectOutputStream(new BufferedOutputStream(new Fi1eOutputstream ( "o.dat")));
		}{
			output.writeUTF("John");
			output.writeDouble(85.5);
			output.writeObject(new java.util.Date());
		}

		try{
			ObjectInputStream input = new ObjectInputStream(FileInoutStream("o.dat"));
		}{
			String name = input.readUTF();
			double score = input.readDouble();
			java.util.Date = (java.util.Date)(input.readObject());
		}
	}
}

2.6 Serializable接口

并不是每一个对象都可以写到输出流。可以写到输出流中的对象称为可序列化的( serializable)。因为可序列化的对象是 java.io.Serializable 接口的实例,所以, 可序列化对象的类必须实现 Serializable 接口
Java 提供一个内在机制自动完成写对象的过程。这个过程称为对象序列化 ( object serialization), 它是在 ObjectOutputStream中实现的。与此相反,读取对象的过程称作对象反序列化 ( object deserialization), 它是在Objectinputstream 类中实现的。
当存储一个可序列化对象时,会对该对象的类进行编码。编码包括类名、类的签名、对象实例变量的值以及该对象引用的任何其他对象的闭包,但是不存储对象静态变量的值。

如果一个对象是 Serializable 的 实例,但它包含了不能序列化的实例数据域,那么可以序列化这个对象吗?答案是否定的。为了使该对象是可序列化的,需要给这些数据域加上关键字 transient, 告诉 Java 虚拟机将对象写入对象流时忽略这些数据域

class A implements java.io.Serializable{
	// 只需序列 化变量 因为 v2 是一个静态变量,所以没有序列化。因为 v3 标记为 transient, 所以也没有序列化
	private int v1;
	private static double v2;
	private transient B v3 = new B();
}

如果一个对象不止一次写入对象流,会存储对象的多份副本吗?答案是不会。第一次写入一个对象时,就会为它创建一个序列号。Java 虚拟机将对象的所有内容和序列号一起写入对象流。以后每次存储时,如果再写入相同的对象,就只存储序列号。读出这些对
象时,它们的引用相同,因为在内存中实际上存储只是一个对象。

2.7 序列化数组

如果数组中的所有元素都是可序列化的,这个数组就是可序列化的。整个数组可以用writeObject 方法存入文件,随后用 readobject 方法恢复。

int[] numbers = {1, 2, 3, 4, 5};
String[] strings = {"John0", "Susan" ,
try (ObjectOutputstream output = newObjectOutputStream(new FlieOutputstream( "array.dat", true));
){
	output.writeObject(numbers);
	output.writeObject(strings);
}

try (Objectinputstream input =
new ObjectInputStream(new Fl1elnputStream("array.dat")) ;
) {
	int[] newNumbers = (int[ ] ) (input.readObject()) ;
	Stringf] newStrings = (String[]) (input .readObject()) ;


for(int i = 0; i < newNumbers.1ength; i++)
	System.out.print(newNumbers[1] + " ");
System.out.println() ;

for(int i = 0; i < newStrings.1ength; i++)
	System.out .print(newStr1ngs[i ] + " ") ;
}

3.随机访问文件

到现在为止,所使用的所有流都是只读的或只写的这些流称为顺序 (sequential) 流。使用顺序流打开的文件称为顺序访问文件。顺序访问文件的内容不能更新。然而, 经常需要修改文件。Java 提供RandomAccessFile 类,允许在文件的任意位置上进行读写。使用 RandomAccessFile类打开的文件称为随机访问文件。
当创建一个 RandomAccessFile 时, 可以指定两种模式 ( “r” 或 “rw”) 之一。模式 "r"表明这个数据流是只读的. 模式 ”rw” 表明这个数据流既允许读也允许写。

RandomAccessFile raf = new RandomAccessFile("test.dat","rw");

如果文件 test.dat 已经存在,则创建 raf 以便访问这个文件;如果 test.dat 不存在,则创建一个名为 test.dat 的新文件,再创建 raf 来访问这个新文件。
在这里插入图片描述
随机访问文件是由字节序列组成的。一个称为文件指针 (file pointer) 的特殊标记定位这些字节中的某个位置。文件的读写操作就是在文件指针所指的位置上进行的。打开文件时,文件指针置于文件的起始位置。在文件中进行读写数据后,文件指针就会向前移到下一个数据项。

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

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

相关文章

深入理解 Linux Zero-copy 原理与实现策略图解

用户态和内核态 一般来说&#xff0c;我们在编写程序操作 Linux I/O 之时十有八九是在用户空间和内核空间之间传输数据&#xff0c;因此有必要先了解一下 Linux 的用户态和内核态的概念。 从宏观上来看&#xff0c;Linux 操作系统的体系架构分为用户态和内核态&#xff08;或者…

昇思25天学习打卡营第24天|ResNet50迁移学习

课程打卡凭证 迁移学习 迁移学习是机器学习中一个重要的技术&#xff0c;通过在一个任务上训练的模型来改善在另一个相关任务上的表现。在深度学习中&#xff0c;迁移学习通常涉及在一个大型数据集&#xff08;如ImageNet&#xff09;上预训练的模型上进行微调&#xff0c;以便…

设计模式之策略模式_入门

前言 最近接触了优惠券相关的业务&#xff0c;如果是以前&#xff0c;我第一时间想到的就是if_else开始套&#xff0c;这样的话耦合度太高了&#xff0c;如果后期添加或者删除优惠券&#xff0c;必须直接修改业务代码&#xff0c;不符合开闭原则&#xff0c;这时候就可以选择我…

vue3.0学习笔记(一)——vue3简介与vite脚手架的使用

1. 为什么学vue3 Vue3现状&#xff1a; vue-next 2020年09月18日&#xff0c;正式发布vue3.0版本。但是由于刚发布周边生态不支持&#xff0c;大多数开发者处于观望。现在主流组件库都已经发布了支持vue3.0的版本&#xff0c;其他生态也在不断地完善中&#xff0c;这是趋势。…

Python | Leetcode Python题解之第268题丢失的数字

题目&#xff1a; 题解&#xff1a; class Solution:def missingNumber(self, nums: List[int]) -> int:n len(nums)total n * (n 1) // 2arrSum sum(nums)return total - arrSum

Qt第十三章 目录和文件操作

目录和文件操作 文章目录 目录和文件操作设备I/O简介I/O设备的类型基本文件读写QFileQTemporaryFile 流操作QTextStreamQDataStream QFileInfoQDirQFileSystemWatcherQStandardPathsQSettings 设备I/O 简介 I/O设备的类型 基本文件读写 QFile QFile file("C:/Users/PV…

Cisco 路由重发布 —— 实现路由信息在不同路由域间的传递

一、技术背景 在实际的组网中&#xff0c;可能会遇到这样一个场景&#xff1a;在一个网络中同时存在两种或者两种以上的路由协议。例如客户的网络原先是纯 Cisco 的设备&#xff0c;使用 EIGRP 协议将网络的路由打通。但是后来网络扩容&#xff0c;增加了一批华为的设备&#…

HAL库源码移植与使用之低功耗模式

低功耗特性对用电池供电的产品&#xff1a; 更小电池体积&#xff08;降低了大小和成本&#xff09; 延长电池寿命 电磁干扰更小&#xff0c;提高无线通信质量 电源设计更简单&#xff0c;无需过多考虑散热问题 电源供电区分为&#xff1a; 分为VDD供电区…

平面五杆机构运动学仿真matlab simulink

1、内容简介 略 89-可以交流、咨询、答疑 2、内容说明 略 ] 以 MATLAB 程序设计语言为平台 , 以平面可调五杆机构为主要研究对象 , 给定机构的尺寸参数 , 列出所 要分析机构的闭环矢量方程 , 使用 MATLAB 软件中 SIMULINK 仿真工具 , 在 SIMULINK 模型窗口下建立数…

深入理解TensorFlow底层架构

目录 深入理解TensorFlow底层架构 一、概述 二、TensorFlow核心概念 计算图 张量 三、TensorFlow架构组件 前端 后端 四、分布式计算 集群管理 并行计算 五、性能优化 内存管理 XLA编译 六、总结与展望 深入理解TensorFlow底层架构 一、概述 TensorFlow是一个开…

从0开始的STM32HAL库学习8

PWM控制舵机 配置环境 1. 选择TIM2时钟 2.选择内部时钟模式&#xff0c;打开通道二 3.分频系数PSC:72-1 自动重装寄存器ARR:20000-1 输出比较寄存器 CCR:500~2500( 后面可调整 ) 脉冲选择500后期可以改 编辑代码 调用启动函数 HAL_TIM_PWM_Start(&htim2,TIM_CHANN…

一分钟图情论文:《智慧数据视角下古籍数字出版的创新路径》

由武汉大学的雷珏莹和王晓光合著的《智慧数据视角下古籍数字出版的创新路径研究》论文从智慧数据1的视角出发&#xff0c;探讨了我国古籍数字出版的现状及其发展瓶颈&#xff0c;提出了古籍数字出版在内容、形式、服务和技术四个方面的创新路径。 文中, 研究者首先详细分析了当…

使用Fiddler进行Android和IOS抓包

Android抓包 要使用Telerik Fiddler Classic捕获Android设备的网络流量&#xff0c;您需要执行以下步骤&#xff1a; 在Fiddler Classic上进行设置&#xff1a; 确保已安装并使用BouncyCastle作为证书生成器。较新的Android版本会拒绝有效期超过两年的证书&#xff0c;目前只…

构建本地智能知识问答系统:基于Langchain和ChatGLM的简单实践

在数字化时代&#xff0c;智能知识问答系统成为了提升企业效率和数据安全性的关键工具。本文将介绍如何基于Langchain和ChatGLM构建一个本地化、支持中文的智能知识问答系统。该系统不仅能够实现完全本地化推理&#xff0c;而且对开源模型友好&#xff0c;可满足企业对数据隐私…

Windows中修改pip下载源

目录 一. 打开此电脑或文件管理器&#xff0c;输入 %APPDATA% 回车跳转 二. 在此目录中新建一个文件夹命令为pip 三. 进入这个目录&#xff0c;新建一个pip.ini文件 四. 复制阿里云镜像配置 五. CMD终端下载验证 六. 常用的国内镜像网站 一. 打开此电脑或文件管理器…

编程中的智慧六:单例、原型、建造者

上一篇咱们结合Spring介绍了设计模式中的工厂模式相关方法&#xff0c;其实现在Java开发基本上都是基于Spring框架开发&#xff0c;所以后续我们在开发过程中基本上很少自己重写一个工厂模式&#xff0c;都是直接使用Spring来完成。今天咱们接着看剩下的创建型设计模式&#xf…

配置VS+VLC并播放视频

文章目录 前言配置VSVLCVLC播放视频基本流程1. libvlc_new2. libvlc_set_user_agent3. libvlc_set_log_verbosity4. libvlc_media_new_path5. libvlc_media_player_new_from_media6. libvlc_media_player_play7. libvlc_media_player_get_state8. libvlc_media_release9. libvl…

使用9种方法隐藏和显示元素

<!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>使用9种方法隐藏和显示元素</title><sty…

Bash 学习摘录

文章目录 1、变量和参数的介绍&#xff08;1&#xff09;变量替换$(...) &#xff08;2&#xff09;特殊的变量类型export位置参数shift 2、引用&#xff08;1&#xff09;引用变量&#xff08;2&#xff09;转义 3、条件判断&#xff08;1&#xff09;条件测试结构&#xff08…

数据结构——栈(顺序结构)

一、栈的定义 栈是一种数据结构&#xff0c;它是一种只能在一端进行插入和删除操作的特殊线性表。这一端被称为栈顶&#xff0c;另一端被称为栈底。栈按照后进先出&#xff08;LIFO&#xff09;的原则进行操作&#xff08;类似与手枪装弹后射出子弹的顺序&#xff09;。在计算…