【javaEE】文件IO

前言:本文将简单介绍一下IO操作、存储、硬盘、文件系统的简单相关常识,相关底层机制和原理实现并不会涉及介绍,如有表述纰漏,还请指出~~

一,硬盘

(一)什么是硬盘

硬盘是计算机中数据存储的物理载体。

(二)硬盘的功能

硬盘的主要功能是实现数据的持久化存储,尽管cpu也可以用于存储数据,但是并不持久,且每次服务的启动都伴随着数据丢失的可能性。所以在实际使用过程中,硬盘往往都是和cpu内存配合工作,协调实现数据存储的。

(三)硬盘类别

当下的硬盘主要可以分为两大类 ,机械硬盘(HDD)和固态硬盘(SSD)

1.机械硬盘(HDD)

机械硬盘顾名思义就是由机械结构组成,在读取数据时磁盘高速旋转,磁头子在旋转的磁盘上顺序读取数据。有点类似于影视剧中看到的黑胶唱片,针头与旋转的唱片接触 发出音乐。但是存储的数据相较于唱片却大了不少

机械硬盘顺序读写快,随机读写慢。

2.固态硬盘(SSD)

固态硬盘就显得小巧了许多,它是电子设备,基于电子闪存来实现数据读取,读写速度,稳定性明显高于固态硬盘。但是同容量的前期下价格高于机械硬盘,也就是除了贵之外没有明显的缺点。

在一般的场景下使用固态硬盘来存储热点数据,减少频繁访问的延迟;使用机械硬盘来低成本存储大容量,低读写的冷数据。

(四)存储

存储是硬盘存储数据的容量大小,一般以GB为单位。这里要注意此存储和cpu的内存是两码事。内存特指CPU的存储空间,比存储空间小,但是贵不少。用于cpu处理任务

存储的特性是持久化,低成本,低容量

二,文件

(一)了解文件

文件在计算机中被广泛运用,查看文件的属性,可以看到具体的文件存储空间大小,文件位置等信息。硬盘是数据存储的物理载体,硬盘位置是在电脑主板上安装的位置。**文件则是操作系统对于硬盘的抽象封装。**可以理解为抽象出来的小型硬盘。对硬盘的抽象便于存储数据的组织管理。

1.组织结构

文件的存储结构视为是树形结构,有着层级关系,根节点root可以简单视为是一个硬盘整体,子文件都是对硬盘的模块化

2.文件路径

硬盘的路径是其物理安装在主板上的位置,文件的路径可以视为文件在计算机硬盘中存储的位置。

文件路径可以用于定位一个文件所在硬盘的位置,一般用于查询文件。

如果把硬盘类比于一座大楼,那么文件就是一间间的公寓,文件路径就是记载着公寓的所在位置便于用户定位查找文件。

文件路径可以分为绝对路径以及相对路径

绝对路径:记载着文件在树形结构上,从根节点到自身的全部详细地址,比如下面的路径就是绝对路径,一般绝对路径都以盘符开头

D:\MAA\MAA-v5.27.2-win-x64
相对路径:表示文件子啊树形结构上,从任意一个节点为起始节点,到该文件所在位置的路径。

相对路径一般推荐在项目中使用,参考系为项目所在的文件位置。比如在写前端文件时,假如使用绝对路径创建一个file对象,代码如下

File f1 = new File("D:\\MyProject\\images\\logo.png");

但当这个代码交付给其他人运行时,可能由于用户的文件名不同导致绝对路径不一致导致运行失败的情况发生,所以这时候建议使用相对路径,

File f2 = new File("images/logo.png");

省略了前面项目所在的文件路径MyProject,这样一来可以保证参考系都可以定位到用户项目所在的位置

3.文件类型

文件类型的划分可以从不同的维度来做出区分,类型有很多。但是假如从计算机存储的角度来看,总体可以分为文本文件二进制文件

文本文件是指定了一套字符编码规则(utf-8/ASCII/GBK),通过编译器按照字符编码能够解析的文件。

二进制文件则纯由0和1组成,并无统一的编码规则。

区分这两个文件的最主要的方式就是通过记事本打开,打开后能看懂的就是文本文件

打开之后一篇乱码的就是二进制文件

比如我们熟知的.jpg格式的图片文件就是二进制文件,记事本打开就会呈现出下面的乱码

三,文件系统

如果说 硬盘 (Hardware) 是一个巨大的仓库,那么 文件系统 (File System) 就是这个仓库的 管理员 + 索引目录

(一)什么是文件系统

操作系统的核心功能是屏蔽计算机硬件的复杂性,为用户统一接口。而文件系统则是操作系统的核心子模块之一,其主要功能就是屏蔽(硬盘/U盘等)存储硬件的复杂性,提供了操作文件的接口和api

(二)文件系统的功能

1.存储空间管理(主要)

如果把硬盘类比于一个很大的存储仓库的话,文件就是一个个单元格子。文件系统负责管理这些格子(文件)的空间分配(给文件中添加内容),数据回收(删除文件中的数据)

2.提供目录和命名

我们在为文件命名时,比如创建一个名为game的文件,文件系统自动会维护一个树形结构(文件/子文件)便于用户管理和访问。而不是让用户在下次想要访问时直接从硬盘中的区域中进行查询数据在哪一个硬盘的区域。

3.地址映射

为什么我们可以直接通过文件的路径来定位到一个文件的所在位置?文件系统负责解决了这个难题。比如用户输入C:\Windows\Web\Wallpaper这样一个绝对路径,文件系统就可以把这个路径实时翻译为操作系统可以识别的语言去查询数据

4.文件安全,权限管理

文件系统负责文件的安全防护,权限管理。当收到进程访问文件的请求时,它会检查进程的访问权限,权限不足则会抛出(Permission Denied)异常

5.故障恢复

当一个进程在向文件中写入数据时,文件系统会提前准备一份文件日志 。当产生突发情况(断电,系统崩溃)时,在重启时文件系统会自动检查 日志来对数据做恢复处理 ,保证数据的一致性

小结:

功能 就像是... 解决的问题
空间管理 仓库管理员 东西该往哪放?哪儿还有空地?
目录管理 图书索引卡 怎么快速找到我要的书?
地址映射 导航仪 "从第几页开始读" -> "去书架第几层拿"
安全保护 门禁系统 闲人免进,防止数据被偷看或篡改。
故障恢复 黑匣子/备忘录 断电了怎么复原现场?

四,IO操作

(一)什么是IO

IO从字面上理解就是input 和 onwrite,即是输入和输出。从计算机这个参考系来看,用户点击鼠标,按下键盘即是输入,电脑返回一个画面,做出响应就是输出。简单来看,IO操作就是系统与外界数据交换的过程

计算机IO操作的核心是为了完成数据的转移

(二)两大IO场景

1.磁盘IO

磁盘IO即是文件读写。其读写效率受限于数据的吞吐量。由于固态硬盘吞吐量大于机械硬盘,所以当下机械硬盘的价格远大于固态硬盘。这也就是为什么说不要把游戏的下载目录设置在机械硬盘上。受限于机械硬盘低吞吐量,在机械硬盘下个大型游戏,等到玩到得不知道下载多久了~~

在java中与之对应的则是:FileInputStream ,FileChannel 等

2.网络IO

网络IO即是网络之间的数据转移,也就是网络通信,这是影响性能的主要原因。其IO效率受限于带宽,网络延迟等多种因素的影响

(二)三种IO模型

1.阻塞IO(BIO - Blocking IO)

如果用烧水的场景来类比,阻塞IO就好比在等待烧水结束的这个过程,由于这个过程耗时,线程(人)只能在那里干等着啥也干不了,就非常影响效率

2.非阻塞IO(NIO - Non-blocking IO)

非阻塞IO好比一个人在烧水的过程中不需要实时在水壶旁边候着,而是可以走开去干别的事。每隔一段时间就返回检查水烧开了没(IO是否完成)。虽然非阻塞IO的这个操作效率相对提升,但是轮询的次数多了,导致占用cpu核心的次数多了,累计一块对cpu也是一个不小的负担

3.IO多路复用(IO Multiplexing ------ 最主流)

多路复用那就不能只烧一壶水了,假设要烧100壶水。我们不需要准备100个人来监控水的状态。而是安排一个管理员(Selector)来监控水的状态。放置水壶的线程可以转头去处理其他的任务,等到水烧开时,由管理员来向对应线程做出报警来处理已经交互好的数据即可

(四)IO为什么慢

(一)原因

以下是IO效率慢在软件上的主要因素

1.用户态,内核态频繁切换

每次 IO 调用(System Call),CPU 都要保存当前程序的现场,切换到内核模式,执行完再切回来(恢复上下文)。这非常消耗资源。

2.多次内存拷贝

硬盘 -> 内核缓冲区 -> 用户缓冲区。数据被重复复制

(二)解决方案

IO性能慢也就是数据转移的效率低下,总共可以从以下几种层面来解决,这里只简单的提供几种可行的解决方案,并不深入阐述其原理

1)硬件层面

最简单的方式就是SSD替换HDD,更新万兆网卡。花钱来解决

2)软件层面
优化策略 (Strategy) 核心原理 (Why it works) Java 对应实现 (How to use) 适用场景 (Scenario)
1. 使用缓冲 (Buffering) 减少系统调用次数。 将多次微小的读写合并为一次大的读写,减少用户态与内核态的切换开销。 推荐BufferedReader / BufferedInputStream 避免Scanner (正则解析慢), 无缓冲的 FileInputStream 所有场景的基础。 尤其是蓝桥杯/算法题中读取大量数据时必用。
2. 顺序读写 (Sequential Access) 减少磁盘寻道时间 (HDD) 或减少闪存擦写开销 (SSD)。 避免磁头在磁盘上跳来跳去。 推荐:利用追加写 (Append-only) 模式。 避免 :频繁使用 RandomAccessFile.seek() 随机跳转。 日志记录、消息队列 (Kafka)。 需要写入海量数据时。
3. 零拷贝 (Zero Copy) 减少 CPU 拷贝次数。 数据直接在内核空间(磁盘->网卡)传输,不经过用户态内存,降低 CPU 负载。 FileChannel.transferTo() FileChannel.transferFrom() 文件服务器、静态资源下载。 需要通过网络发送大文件时。
4. 内存映射 (Memory Mapped / mmap) 利用虚拟内存。 将文件直接映射到内存地址,像操作数组一样操作文件,省去 buffer 拷贝。 FileChannel.map() 得到 MappedByteBuffer 超大文件处理 (GB级别)。 如数据库索引文件、极大的日志分析。
5. IO 多路复用 (Multiplexing / NIO) 减少线程切换开销。 用一个线程监控成千上万个连接的状态,避免为每个连接创建一个线程。 Selector + Channel + Buffer (通常直接使用 Netty 框架) 高并发网络应用。 如聊天室、网关、RPC 框架。

有关文件IO的相关知识点就简单介绍到这里了,如有纰漏,还请大佬即使指出捏~~

相关推荐
微露清风2 小时前
系统性学习Linux-第一讲-Linux基础指令
java·linux·学习
tqs_123452 小时前
tcc中的空回滚和悬挂问题
java·数据库
MX_93592 小时前
以配置非自定义bean来演示bean的实例化方式
java·开发语言·后端
哪里不会点哪里.2 小时前
Spring 事务机制详解:原理、传播行为与失效场景
java·数据库·spring
风筝在晴天搁浅3 小时前
hot100 102.二叉树的层序遍历
java·算法
lina_mua3 小时前
Cursor模型选择完全指南:为前端开发找到最佳AI助手
java·前端·人工智能·编辑器·visual studio
秋93 小时前
idea中如何使用Trae AI插件,并举例说明
java·人工智能·intellij-idea
输出输入3 小时前
JAVA中return和break区别
java
董世昌413 小时前
null和undefined的区别是什么?
java·前端·javascript