欢迎浏览高耳机的博客
希望我们彼此都有更好的收获
感谢三连支持!
在计算机科学中,IO(输入/输出)、存储、硬盘和文件系统是构成计算机数据处理和存储的基础。本文将探讨这些概念,特别是文件系统的工作原理和相关知识。
输入/输出(IO):计算机的感官
IO是计算机与外部世界交互的桥梁。它包括了所有形式的数据输入和输出操作。当我们在键盘上敲击文字、用鼠标点击链接、或者在屏幕上查看图片时,这些都是IO操作的实际应用。在计算机内部,IO操作也发生在硬件设备之间,比如CPU与内存之间的数据交换。
IO的类型
- 硬件IO:涉及计算机硬件设备,如键盘、鼠标、显示器、打印机等。
- 网络IO:涉及网络数据的传输,如通过互联网下载文件或发送电子邮件。
- 磁盘IO:涉及硬盘或其他存储设备的读写操作,是计算机存储数据的主要方式。
存储与硬盘:数据的物理载体
存储设备是计算机系统中用于保存数据的硬件。它们可以是临时的,如RAM(随机存取存储器),也可以是永久的,如硬盘。硬盘作为最主要的永久存储设备,其容量和性能直接影响到计算机的整体表现。
硬盘的演变
- 传统硬盘(HDD):使用磁性碟片存储数据,体积较大,速度相对较慢。
- 固态硬盘(SSD):使用闪存技术,体积小巧,读写速度快,耐用性高,但成本相对较高。
随着技术的进步,SSD正逐渐取代HDD,成为主流的存储设备。
文件系统:组织和管理数据的框架
文件系统是操作系统用于管理存储设备上文件和目录的一种机制。它定义了文件的存储方式、目录结构、以及如何访问和操作这些文件。
狭义上的文件
针对硬盘这种持久化存储的I/O设备,当我们想要进行数据保存时,往往不是保存成⼀个整体,而是独立成⼀个个的单位进行保存,这个独立的单位就被抽象成文件的概念.文件除了有数据内容之外,还有一部分信息,例如文件名、文件类型、文件大小等并不作为文件的数据而存在,我们把这部分信息可以视为文件的元信息。
树型结构组织和目录
同时,随着文件越来越多,对文件的系统管理也被提上了日程,如何进行文件的组织呢,一种合乎自然的想法出现了,就是按照层级结构进行组织——也就是数据结构中的树形结构。这样, 一种专门用来存放管理信息的特殊文件诞生了,也就是我们平时所谓的文件夹(folder)或者目录(directory)的概念。
文件路径(Path)
如何在文件系统中如何定位一个唯一的文件就成为当前要解决的问题,从树型结构的角度来看,树中的每个节点都可以被一条从根开始,一直到达成的节点的路径所描述,而这种描述方式就被称为文件的绝对路径(absolute path)。
除了可以从根开始进行路径的描述,我们可以从任意节点出发,进行路径的描述,而这种描述方式就被称为相对路径(relative path),相对于当前所在节点的一条路径。
文件系统的核心功能
- 数据存储:将数据以文件的形式保存在存储设备上。
- 目录结构:通过目录和子目录组织文件,形成树状结构,方便用户导航和查找。
- 文件访问:控制用户对文件的访问权限,确保数据安全。
- 数据恢复:在文件损坏或丢失时,提供恢复机制。
文件系统的多样性
不同的操作系统有不同的文件系统实现。例如:
- Windows:使用NTFS或FAT32文件系统,文件名的后缀用于区分文件类型。
- macOS:使用APFS或HFS+文件系统,不依赖文件名后缀来识别文件类型。
- Linux:使用ext4、XFS等文件系统,同样不依赖文件名后缀。
这种多样性意味着跨平台操作时需要考虑文件系统的兼容性。
Java中的文件操作:实践文件系统知识
Java提供了丰富的API来操作文件和目录。通过java.io.File
类,我们可以轻松地进行文件的创建、删除、重命名等操作。此外,Java的数据流类库,如InputStream
和OutputStream
,允许我们以字节为单位进行文件的读写操作。
我们先来看看 File 类中的常见属性、构造方法和方法:
属性:
修饰符及类型 | 属性 | 说明 |
static String | pathSeparator | 依赖于系统的路径分隔符,String类型的表示 |
static char | pathSeparator | 依赖于系统的路径分隔符,char类型的表示 |
构造方法:
签名 | 说明 |
File(File parent, String child) | 根据父目录 + 孩子文件路径,创建一个新的File实例 |
File(String pathname) | 根据文件路径创建一个新File实例,路径可以是绝对路径或者相对路径 |
File(String parent, String child) | 根据父目录 + 孩子文件路径,创建一个新File实例,父目录用路径表示 |
方法:
修饰符及返回值类型 | 方法签名 | 说明 |
String | getParent() | 返回File对象的父目录文件路径 |
String | getName() | 返回File对象的纯文件名称 |
String | getPath() | 返回File对象的文件路径 |
String | getAbsolutePath() | 返回File对象的绝对路径 |
String | getCanonicalPath() | 返回File对象的修饰过的绝对路径 |
boolean | exists() | 判断File对象描述的文件是否真实存在 |
boolean | isDirectory() | 判断File对象代表的文件是否是一个目录 |
boolean | isFile() | 判断File对象代表的文件是否是一个普通文件 |
boolean | createNewFile() | 根据File对象,自动创建一个空文件,成功创建后返回true |
boolean | delete() | 根据File对象,删除该文件。成功删除后返回true |
void | deleteOnExit() | 根据File对象,标注文件将被删除,删除动作会到JVM运行结束时才会进行 |
String[ ] | list() | 返回File对象代表的目录下的所有文件名 |
File[ ] | listFiles() | 返回File对象代表的目录下的所有文件,以File对象表示 |
boolean | mkdir() | 创建File对象代表的目录 |
boolean | mkdirs() | 创建File对象代表的目录,如果必要,会创建中间目录 |
boolean | renameTo(File dest) | 进行文件改名,也可以视为我们平时的剪切、粘贴操作 |
boolean | canRead() | 判断用户是否对文件有可读权限 |
boolean | canWrite() | 判断用户是否对文件有可写权限 |
代码示例
示例1:get系列的特点和差异
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
File file = new File("..\\hello-world.txt"); // 并不要求该文件真实存在
System.out.println(file.getParent());
System.out.println(file.getName());
System.out.println(file.getPath());
System.out.println(file.getAbsolutePath());
System.out.println(file.getCanonicalPath());
}
}
运行结果
..
hello-world.txt
..\hello-world.txt
D:\代码练习\文件示例1\..\hello-world.txt
D:\代码练习\hello-world.txt
这些输出分别对应于:
file.getParent()
:返回的是文件的父目录,由于文件路径是相对的,并且指向上一级目录,所以这里只返回了两个点(..)表示上一级目录。
file.getName()
:返回的是文件的名称,这里是hello-world.txt
。
file.getPath()
:返回的是文件的路径,这通常与构造函数中提供的路径相同,这里是..\hello-world.txt
。
file.getAbsolutePath()
:返回的是文件的绝对路径,这是根据当前工作目录解析相对路径后得到的,这里是D:\代码练习\文件示例1\..\hello-world.txt
。
file.getCanonicalPath()
:返回的是文件的规范化绝对路径,这意味着路径中的.
和..
已经被解析,这里是D:\代码练习\hello-world.txt
。这个路径表示文件实际上位于D:\代码练习
目录下。
示例2:普通文件的创建
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
File file = new File("hello-world.txt"); // 要求该文件不存在,才能看到效果
System.out.println(file.exists());
System.out.println(file.isDirectory());
System.out.println(file.isFile());
System.out.println(file.createNewFile());
System.out.println(file.exists());
System.out.println(file.isDirectory());
System.out.println(file.isFile());
System.out.println(file.createNewFile());
}
}
运行结果
false
false
false
true
true
false
true
false
这些输出分别对应于:
file.exists()
:在文件不存在时,返回false
。file.isDirectory()
:在文件不存在时,返回false
,因为无法判断它是否是一个目录。file.isFile()
:在文件不存在时,返回false
,因为无法判断它是否是一个文件。file.createNewFile()
:尝试创建文件,如果成功则返回true
。file.exists()
:在文件被成功创建后,返回true
。file.isDirectory()
:检查新创建的文件是否是目录,返回false
,因为它是一个文件。file.isFile()
:检查新创建的文件是否是文件,返回true
。file.createNewFile()
:再次尝试创建已存在的文件,返回false
,因为文件系统不允许创建已存在的文件。
示例3:普通文件的删除
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
File file = new File("some-file.txt"); // 要求该文件不存在,才能看到相应效果
System.out.println(file.exists());
System.out.println(file.createNewFile());
System.out.println(file.exists());
System.out.println(file.delete());
System.out.println(file.exists());
}
}
运行结果
false
true
true
true
false
这些输出分别对应于:
file.exists()
:在文件不存在时,返回false
。file.createNewFile()
:尝试创建文件,如果文件成功被创建,返回true
。file.exists()
:在文件被创建之后,再次检查文件是否存在,返回true
。file.delete()
:尝试删除已存在的文件,如果文件成功被删除,返回true
。file.exists()
:在文件被删除之后,再次检查文件是否存在,返回false
,因为文件已经被删除。
示例4:观察 deleteOnExit
的现象
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
File file = new File("some-file.txt"); // 要求该文件不存在,才能看到相应效果
System.out.println(file.exists());
System.out.println(file.createNewFile());
System.out.println(file.exists());
file.deleteOnExit();
System.out.println(file.exists());
}
}
运行结果
false
true
true
true
这些输出分别对应于:
file.exists()
:在文件不存在时,返回false
。file.createNewFile()
:尝试创建文件,如果文件成功被创建,返回true
。file.exists()
:在文件被创建之后,返回true
,因为文件现在已经存在。file.deleteOnExit()
:这个方法会请求在虚拟机终止时删除文件。调用这个方法后,file.exists()
的返回值仍然是true
,因为文件还没有被删除,deleteOnExit
只是标记了这个文件在JVM退出时应该被删除。
请注意,deleteOnExit()
方法的效果不会立即显现,它只有在JVM终止时才会执行删除操作。这意味着,即使你调用了deleteOnExit()
方法,文件在程序运行期间仍然存在,直到JVM退出。如果你想验证deleteOnExit()
的效果,你需要在程序运行结束后检查文件是否被删除。
示例5:观察目录的创建
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
File dir = new File("some-dir"); // 要求该目录不存在,才能看到相同的现象
System.out.println(dir.isDirectory());
System.out.println(dir.isFile());
System.out.println(dir.mkdir());
System.out.println(dir.isDirectory());
System.out.println(dir.isFile());
}
}
运行结果
false
false
true
true
false
这些输出分别对应于:
dir.isDirectory()
:在目录不存在时,返回false
。dir.isFile()
:在目录不存在时,同样返回false
,因为该路径既不表示一个已存在的目录也不表示一个文件。dir.mkdir()
:尝试创建目录,如果目录成功被创建,返回true
。dir.isDirectory()
:在目录被创建之后,返回true
,表明该路径现在指向一个存在的目录。dir.isFile()
:在目录存在的情况下,返回false
,因为该路径现在指向一个目录而不是一个文件。
理解了以上文件系统的基本操作,下一篇博客我将介绍IO流 InputStream, OutputStream 的用法,跳转链接:【Java】IO流:InputStream与OutputStream实战指南-CSDN博客
希望这篇博客能为你理解IO操作以及文件系统提供一些帮助
如有不足之处请多多指出
我是高耳机