Java I/O学习笔记

编程自学指南:java程序设计开发,Java高级API-I/O 流学习笔记 编程自学指南:java程序设计开发,Java高级API-I/O 流学习笔记,流是一组有顺序的、有起点和终点的数据集合,它是对数据传输的一种抽象表述。Java 中的 I/O 流用于处理不同类型的数据传输,如文件读写、网络通信等。 阅读详情

Java I/O学习笔记


一. Java I/O的几个基本概念

1. “流”的概念:Java I/O在设计的过程中,最核心的概念就是“流”(Stream)。所谓的“流”是完全可以被比拟成生活中的自然现象,比如水流。在获取某个数据的过程中,数据的来源相当于水源;数据被一个具体的类读取时,就相当于水源被从水管中引导到我们所需要的地方,处理数据的类就相当于水管。当多个类套接起来处理该数据源的数据时,就相当于多个水管连接在一起,套接的类增加了处理数据的方式,连接的水管可以改变水流的方向,这是一个道理。

2. input和output: 在Java I/O中,接口和类被分成input和output两大块。无论是以字节形式处理还是以字符的形式处理,按照输入还是输出就能快速找到想要的处理类。

3. 装饰模式:Java I/O大量采用装饰模式。所谓装饰模式也就是在概念1中提到的将多个类套接起来处理数据源流出的数据。
比如:DecoratorB decoratorB = new DecoratorB(new DecoratorA(object));
DecoratorB接装饰了DecoratorA,在提供和DecoratorA具有相同名称但是功能更多的方法以外,DecoratorB也可以增加自己的方法来丰富对object的操作。在学习I/O的过程中会逐渐明白装饰模式的使用,只要真正理解装饰模式,I/O的操作其实就是选择合适类来进行组合的问题了。

二. Java I/O包的基本结构

Java I/O包可以分为三部分。
1. 流式部分:在流式部分,又可以分为字节流和字符流。字节流包含了InputStream,OutputStream,FilterInputStream,FilterOutputStream四块,字符流包含了Reader和Writer两块(具体结构参见后面的字节流和字符流部分)。
2.非流式部分:主要是一些I/O处理所需要的类,最常用的就是File类和RandomAccessFile类。
3.其他:比如用于序列化的Serializable接口等等。

三. 字节流

所谓字节流,意思就是说以字节为单位来从数据源处读取数据,并向输出端按字节方式输出。

输入端:
处理字节流读取的类都继承了InputStream抽象类,比如FileInputStream用来读取文件中的字节。
用法是 InputStream input = new FileInputStream(new File("xxx")); 
如果将上述语句中FileInputStream替换成其他继承InputStream的类,我们就可以读取来自其他数据源的字节数据。

当我们想在读出字节的时候提供更多的操作时,比如我们想从FileInputStream里面读出以二进制形式所存储的整数(注意二进制所存储的整数和以字符表示整数是不一样的概念。比如'20',在二进制存储时占4个字符,在ASCII编码字符表示是占两个字符),那么就会用到DataInputStream类来装饰。
用法是 InputStream input new DataInputStream(new FileInputStream(new File("xxx"))); 然后再调用DataInputStream的readInt()方法。
所有的装饰类都继承自FilterInputStream类,而FilterInputStream是InputStream的子类。

综上所述,一个完整的字节流输入可以按如下方法读取:
InputStream input = new InputStreamDecoratorClass(new InputStreamSubClass(resource object));

字节输入端的常用类包结构如下:
InputStream
----FileInputStream 读取文件
----ByteArrayInputStream 读取JVM运行内存中的byte数组,免除存储和删除的操作
----SequenceInputStream 合并多个InputStream流
----PipedInputStream 线程间通讯用
----ObjectInputStream 序列化对象读取
----FilterInputStream InputStream所有装饰类的父类
     ----DataInputStream 可以读取各种Java的primitive type
     ----BufferedInputStream用来以缓存的方式读取流,极大提高读取性能。要注意的是,在调用close()方法前记得调用flush()方法。

输出端:
原理和输入端一样,只不过是将JVM内存中的数据以字节的形式输出。
使用方法:
OutputStream input = newOutputStreamDecoratorClass(newOutputStreamSubClass(resource object));

字节输出端的常用类包结构如下:
OutputStream
----FileOutputStream 输出文件
----ByteArrayOutputStream输出JVM运行内存中的byte数组,免除存储和删除的操作
----SequenceOutputStream 合并多个OutputStream流
----PipedOutputStream 线程间通讯用
----ObjectOutputStream 序列化对象输出
----FilterOutputStreamOutputStream所有装饰类的父类
     ----DataOutputStream 可以输出各种Java的primitive type
     ----BufferedOutputStream 用来以缓存的方式输出流,极大提高输出性能
     ----PrintStream 提供格式化输出的方式

在字节输出端值得一提的是PrintStream类,这个类也是我们常用的System.out对象的类型。
所谓的格式化输出,就是能够在字节输出的基础上添加一些格式。比如最常用的System.out.println(a string”),就是在输出一个String的同时,添加了一个换行字符。更多的格式化输出方式可以参考Java API。

PrintStream类还有两个特点:一个是,该类任何写入方法都调用了它所装饰的OutputStream类的flush()方法,这也就意味着我们不需要显示地调用flush()方法了。二个是:该方法不会抛出异常,所有的被装饰的OutputStream类如果抛出InterruptedIOException,则按Thread.currentThread().interrupt(); 处理,对于其他抛出的IOException,PrintStream用一个私有布尔型trouble标注,通过checkError()方法来反馈。

四. 字符流

字符流是以面向字符的方式来处理I/O流的。所谓面向字符,就是说在程序读入读出的过程中,操作的不再是一个个字节,而是以字符char作为基本操作单元。这样通过字符流相关的类,我们就可以方便的读取和操作文本文件,并且可以使用String类等所提供的便捷方法。字符流是对字节流的一个封装,也就是说,在字节流的基础上,Java提供相关类的相关方法通过对不同编码方式文本文件的内容按字节读取然后转换成Java的Unicode表示方法。在输出端则是将Java的Unicode表示的字符,通过相关方法的转换成字节,然后一个一个写入文件。


同字节流一样,字符流也分为input和output两个部分。

输入端:

所有输入端的字符流处理类都继承Reader抽象类,包结构如下:

Reader

----InputStreamReader

    ----FileReader

----CharArrayReader

----StringReader

----PipedReader

----BufferedReader

其中InputStreamReader最为关键。因为它是将字节流转换成字符流的中间桥梁,这可以通过它的构造方法看出。而其他类在构造的时候都基于一个现成的Reader对象(也就是由InputStreamReader转化所得的Reader对象)。具体解释参见下一节。


输出端:

所有输出端的字符流处理类都继承了Writer抽象类,包结构如下:

Writer

----OutputStreamWriter

    ----FileWriter

----CharArrayWriter

----StringWriter

----PipedWriter

----BufferedWriter

在输出端作为桥梁的类是OutputStreamWriter。其余类的工作方式和输入端相同。


五. 字节流与字符流的转换

字节流可以通过某些类转变成字符流。最常用的有:
输入端 InputStreamReader input=new InputStreamReader(new FileInputStream(new File("D:/input.txt")));
输出端 OutputStreamWriter output=new OutputStreamWriter(new FileOutputStream(new File("D:/output.txt")));

在学习整理的过程中,我一直在想究竟字节流是怎样被转换成字符流的。经过一番查询和实验,这个问题终于有了一个比较清晰的回答。

第一点:一个byte是8个bit,一个char是两个byte。所有文件都是由byte组成的,无论是文本文件还是图像文件等等。而char则是java的一个基本类型,它是java在类存中存储字符的表现形式。
第二点:Java存储在内存中的char采用的是Unicode字符集,而文本文件存储在硬盘中的时候会被系统用指定的编码存储。字符集和编码是不同的概念。比如说Unicode定义了不同字符对应不同的数值,而UTF-8, UTF-16等是实现Unicode的编码形式。
第三点:Java在实现字节流与字符流转换的过程中,其实是将输入端不同的编码方式翻译成Unicode字符集所映射的数值,并在内存中对这些数值(即char)进行操作,最后在输出端将Unicode映射的数值转化成具体的编码方式输出。若没有指定输入输出的字符集,则Java默认采用系统默认编码方式。字符的概念仅存在于Java运行内存当中,与实际文件的存储没有关系。

实例:
在hello.txt中只包含了一个“好”字,我的系统默认编码是UTF-8,并且hello.txt采用无BOM的UTF-8。
public class EncodingTest {
	public static void main(String[] args) throws IOException {
		File file = new File("D:/hello.txt");
		System.out.println(file.getName() + "长度为: " + file.length() + " bytes");

		// 以字节流方式读入文件
		InputStream input = new FileInputStream(file);
		byte[] b = new byte[10];
		input.read(b);
		for (int i = 0; i < file.length(); i++) {
			System.out.println("字节 " + i + ": " + Integer.toHexString(b[i]));
		}
		input.close();
		System.out.println();

		// 以字符流方式读入文件
		input = new FileInputStream(file);
		Reader reader = new InputStreamReader(input);
		char c = (char) reader.read();
		System.out.println(file.getName() + "内容为: " + c);
		input.close();
		System.out.println();

		// ‘好’字的Unicode为22909
		System.out.println("'好'的Unicode二进制: " + Integer.toBinaryString(22909));
	}
}
输出为:
hello.txt长度为: 3 bytes
字节 0: ffffffe5
字节 1: ffffffa5
字节 2: ffffffbd

hello.txt内容为: 好

'好'的Unicode二进制: 101100101111101

在以字节流读入的时候,程序读出3个字节。在UTF-8中,“好”字对应的编码是 1110 0101 10 10 0101 10 11 1101。
在以字符流读入的时候,程序将UTF-8编码转变成“好”字的Unicode所对应的数值。“好”字在Unicode中对应的数值为22909, 二级制表示为 0101 1001 0111 1101。
通过UTF-8编码方式,将Unicode带入验证,所得结果即为所显示的三个字节组合。

至此,字节流转换成字符流的过程基本解释完毕。

六. I/O中有关buffer的使用

buffer的作用通过将数据暂时存放在内存中,从而降低程序和物理存储的读写次数来提高程序的效率。
字节流中操作buffer的相关类为BufferedInputStream和BufferedOutputStream。在这两个类中作为缓存的是一个byte数组。
字符流中操作buffer的相关类为BufferedReader和BufferedWriter。在这两个类中作为缓存的是一个char数组。

七. File类和RandomAccessFile类

在Java I/O范围类,还有一些非流式操作的类也很重要。比如File类和RandomAccessFile类。
File类:
File类是文件系统中所有文件的一个抽象。当File类被实例化的时候,它描述了一个由file path(文件路径)所指向的文件系统上的一个文件。通过调用File类的方法可以对文件进行添加,删除,获取长度等等操作。注意File类的作用是获取某个文件的相关信息,而不表示文件的具体内容。对应文件具体内容的操作,还要参照Java I/O中关于流的造作类。

RandomAccessFile类:
RandomAccessFile类对于文本文件的读写操作非常方面。
首先,该类允许对一个文件同时进行读与写的操作。也就是说将input和output操作整合到一起。
其次,该类即可以操作字节流也可以操作字符流,提供各种对Java基本类型的读入与输出的方法。
最后,该类提供文件内置指针操作,可以从指定的offset处读入或写入数据。比如seek(long pos)方法,就允许将指针设定在具体的位置,下一次read或者write就从该指针处进行。

八. 对象序列化

Java I/O关于对象序列化设计两个内容,一个是什么样的对象可以被序列化,二个是如何读入和输出被序列化的对象。

1. 创建可以被序列化的对象
一般情况下,当一个class实现了Serializable接口,那么这个class的实例就可以被序列化了。语法如下:
class XXX implements Serializable { }

在对象序列化的过程中,只有该对象的属性被序列化类。如果想要读取出这个序列化的对象,那么在读取程序的类路径中一定要包含该class,否则自然没有办法还原这个对象了。如果对于一个要进行的序列化的class,我们只希望序列化它的一部分属性,忽略某些敏感信息(比如 String password),那么我们就在这些不想被序列化的属性前加上transient关键字。

当程序员想能够自由的掌控序列化的过程,也就是说自定义序列过程的输入输出,那么就要实现Externalizable接口。语法如下:
class XXX implements Externalizable { }
实现Externalizable接口,意味着要实现readExternal(ObjectInput in)和writeExternal(ObjectOutput out)这两个方法。在这两个方法中,我们可以定义要序列的属性。这两个方法分别会被ObjectInputStream中的readOrdinaryObject()和ObjectOutputStream中的writeOrdinaryObject()方法所调用。

两点注意:
实现序列化的class要显示的写出无参数构造方法,这样可以避免在反序列化过程中抛出异常。
在实现readExternal(ObjectInput in)和writeExternal(ObjectOutput out)这两个方法时,读入和输出属性的顺序一定要一致,否则也会抛出异常。这是因为属性在被序列化成二进制码的过程中,都是按顺序输出和读入的。

2. 序列化对象的读入和输出
序列化对象的输出需要用到ObjectOutputStream类,调用writeObject()方法。
序列化对象的读入需要用到ObjectInputStream类,调用readObject()方法。

九. 参考

[1] 字符编码笔记:ASCII,Unicode和UTF-8

http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html (该博主将编码方式,字符集等原理解释的非常清楚!)
http://www.cnblogs.com/rollenholt/archive/2011/09/11/2173787.html ( 该博主通过大量实例详细讲解了Java I/O中各个类的使用,非常值得一读!)

【Java学习笔记】16. I/O系统 输入/输出(Input/Output)是指对某个物理或逻辑设备或某种㡳进行数据的输入或输出。例如:对服务器主机数据的读/写、摄像头视频数据的输入、本地文件的输入/输出等。由于数据存取的环境和设备不同,所以数据的读/写方案具有多样性。输入/输出问题在程序射击中是一个复杂的问题。java针对这个问题,提出了自己的解决方案——流(Stream)对象。对不同的输入/输出问题提供了不同的流对象。所有的数据都可以使用流写入和读出。流是程序中数据传输的一条路径。 阅读详情

相关推荐

javaIO流笔记

详解java中Io流的运用,并且有实例做出说明

Java IO流学习总结

Java流操作有关的类或接口: Java流类图结构:   流的概念和作用 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。  IO流的分类 根据处理数据类型的不同分为:字符流和字节流 根据数据流向不同分为:输入流和输出流   字符流...

weixin_33895516的博客 1324

Java I/O详细笔记

Java I/O详细笔记

Java 学习笔记:IO 系统

概览 Java 的 I/O 大概可以分为以下几类: 磁盘操作:File 字节操作:InputStream 与 OutputStream 字符操作:Reader 与 Writer 对象操作:Serializable 网络操作:Socket 新的输入 / 输出:NIO 磁盘操作 File 类可以用于表示文件和目录的信息,但是它不表示文件的内容。 // 递归地列出一个目录下所有文件 public s...

Breadcrumb Trails 233

攻克TypeError: Cannot read properties of undefined (reading ‘NormalModule‘)的四种实战策略

本文详细解析了`TypeError: Cannot read properties of undefined (reading 'NormalModule')`错误的四种实战解决策略。从版本一致性检查、包管理器优化到依赖替换和构建环境配置,帮助开发者快速定位和解决Webpack构建过程中的常见问题,提升开发效率。

weixin_42523670的博客 243

K-近邻算法: k-nearest neighbor classification (kNN) 详细介绍

@创建于:2020.04.09 @修改于:2020.04.09,2024.06.22 文章目录1、kNN介绍2、k近邻法的三要素详解2.1 距离度量2.2 k值的选择2.3 分类决策规则3、k近邻法的实现:kd树4、Python实现过程5、优缺点6、常见问题 1、kNN介绍 kNN是一个基本而简单的分类算法,作为监督学习,那么KNN模型需要的是有标签的训练数据,对于新样本的类别由与新样本距离最近的k个训练样本点按照分类...

chenhepg的博客 9万+

java I/O编程 学习笔记

java I/O 学习笔记 一、文件对象 File类,就是文件对象 基础操作,文件删除,是否存在等 import java.io.File; public class javaDemo{ public static void main(String[] args) throws Exception { File file = new File("file.txt");...

yaologos的博客 255

【C++PTA】6-1 Point类的运算 (10 分)

定义Point类,有坐标x,y两个私有成员变量;对Point类重载“+”(相加)、“-”(相减)和“==”(相等)运算符,实现对坐标的改变,要求用友元函数和成员函数两种方法实现。对Point类重载<<运算符,以使得代码 Point p; cout<<p<<endl;可以输出该点对象的坐标。 函数接口定义: 实现Point类。 裁判测试程序样例: /* 请在这里填写答案 */ int main(int argc, char const *argv[]) { P

libertye的博客 2367

《Java面向对象编程》学习笔记16—Java I/O系统

本文已搬家至【Java学习笔记】I/O体系

gnuhpc的专栏 3184

vSphere环境证书更新/续订案例及注意事项

早期VMware的用户随后“十年之期”已到,陆陆续续出现各种登录问题,证书报错告警等,主要包含6.5到7.0的版本,VMware服务器虚拟化环境涉及的证书及类型较多,在实际更新中会出现各种奇怪的问题,有些坑耗费了大量的troubleshooting时间,极端情况下一天能看到十多遍如下报错😂本文整理了一个近期的更新案例,以及之前处理过的一些问题,仅作参考CA根证书颁发机构,用于签发其他组件的证书,其他证书的有效期不会超过根证书。

RaySun的技术Blog 3203

ST MCSDK V6.2.0实战:手把手教你配置HSO-ST观测器,体验500ms收敛的电机无感控制

本文详细介绍了ST MCSDK V6.2.0中HSO-ST观测器的配置方法,实现500ms内电流收敛的无感电机控制。从环境搭建、核心参数解析到无感启动优化,提供实战技巧和性能调优策略,帮助开发者快速掌握高效电机控制技术。

weixin_28720767的博客 580

7.19-7.20 Java基础 | File类 I/O流学习笔记

write。

weixin_47011416的博客 831

泛微OA与金蝶云星空审批流程对接实战:从报销单到采购合同的完整指南

本文详细介绍了泛微OA与金蝶云星空审批流程的深度集成方案,涵盖从报销单到采购合同的完整对接指南。通过API层面的无缝连接,实现流程自动化、数据同源和权限联动,显著提升企业业务效率。文章还提供了环境配置、数据映射、接口安全等实用技巧,助力企业轻松完成系统对接。

weixin_29268637的博客 245

Java筑基——I/O系统学习笔记

之前工作中接触 I/O 较少,只是用一些工具类处理问题。以为这样就可以了。后来在工作中用到多文件传输,文件合并,感到I/O流知识的欠缺。现在有时间把它们总结一下,写成本文。

willwaywang6 1490

【Bug已解决】codex: tool call timeout / Function execution exceeds limit — CodeX CLI 工具调用超时解决方案

CodeX CLI 工具调用超时(Bash/文件/MCP)的解决方案,含增加超时、拆分命令、后台运行、避免交互卡住与限制读取。

博客 4204

【WorkBuddy专栏52】Codex与WorkBuddy生态适配、用户争夺与未来走向(下)

【WorkBuddy专栏52】Codex与WorkBuddy在中国大陆的发展——生态适配、用户争夺与未来走向(下)

AI人人懂 679

【Java学习笔记】I/O实例

-----------------------------------------------个人初学,如有错误,欢迎指正----------------------------------------------- Java I/O 初学,实例讲解 一、简介: 上篇博文介绍了Java中常用的I/O操作,本篇博文是对上篇的补充,主要列举以下实例,帮助大家更好的理解I/O操作: 1、

VisionDo的博客 540

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

java file I o笔记_Java学习笔记-I/O

File类一个File类的对象,表示了磁盘上的文件或目录。File类提供了与平台无关的方法来对磁盘上的文件或目录进行操作。import java.io.*;class FileTest{public static void main(String[] args) throws Exception{//File f = new File("1.txt");//f.createNewFile();...

weixin_34175189的博客 191

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Java学习笔记——I/O流

文章目录I/O流I/O流简介(分类与体系结构)File类构造File类对象File类对象可以执行的操作IO详解节点(文件)流节点(文件)流(字符读入读出)节点(文件)流(字节读入读出)缓冲流小结 I/O流 I/O流简介(分类与体系结构) I/O流是java中负责文件输入输出的模块,用于处理设备之间的数据传输,例如读/写文件,网络通信等。通常,我们在java中写程序时,是站在内存的角度,硬盘中的各种程序读入内存的过程是input,从内存中写入硬盘的过程是output。 java的IO流中有各种各样的流,根据不

weixin_43725818的博客 267

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

【学习笔记】JAVA I/O框架

JAVA I/O框架1. 什么是流?2. 流的分类:3 字节流3.1 FileInputSteam的使用(文件字节流的使用)3.2 FileOutputStream的使用3.3 字节流复制文件3.4 字符缓冲流3.5 BufferedInputStream的使用3.6 BufferedOutputStream的使用4. 对象流4.1 序列化4.2 反序列化4.3 序列化和反序列化注意事项5 字符流5.1 常见字符编码5.2 字符流抽象类5.3 FileReader的使用5.4 FileWriter的使用5.

prague6695的博客 407

Java学习笔记之I/O流

I/O流前言一、字节流1.1 字节流输入InputStream1.1.1常用方法1.1.2常用类1.2字节流输出OutputStream1.2.1常用类1.2.2常用方法二.字符流2.1字符输入流抽象类Reader2.1.1常用方法2.1.2常用类2.2 字符流输出Writer2.2.1常用方法2.2.2常用类三、File类3.1常用方法四、ZIP压缩输入流/输出流1.压缩ZipOutputStream1.压缩方法2.解压缩ZipInputStream2.1常用方法总结 前言 学习I/O流首先需要了解字节

qq_45188626的博客 157

Netty学习笔记之Java I/O

Netty学习笔记第一部分

举个锤子的博客 376

Java之I/O 流学习笔记

java I/O流学习笔记

MRS_jianai的博客 133

深入分析Java I/O的工作机制 学习笔记

1.Java I/O的基本架构 1.1Java的I/O操作类在包java.io下,大概有80个类,大概分为以下四组 基于字节操作的I/O接口:InputStream和OutputStream 基于字符操作的I/O接口:Writer和Reader 基于磁盘操作的I/O接口:File 基于网络操作的I/O接口:Socket Socket接口不在java.io包下 前两组主要是传输数据的数据格式 后两...

zzw_17600691357的博客 244
上一篇: Java Annotation学习笔记
下一篇: Java Enum学习笔记
AlainGogogo
博客等级 码龄18年 5粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值