文件的逻辑结构以及索引文件
文件的逻辑结构 (Logical File Structure)
文件的逻辑结构是指在用户看来,文件是由什么信息成分构成的,以及成分之间的关系。它关注的是文件的组织方式,而不是存储方式。从用户的角度,文件主要可以分为以下两种逻辑结构:
1. 无结构文件 (流式文件 - Stream of Bytes File)
这是最简单、也是当今最常用的文件逻辑结构。
-
核心思想: 文件就是一个连续的、无差别的字节序列 (Stream of Bytes)。操作系统不关心文件中存储的是什么,无论是文本、图像还是可执行代码,在操作系统看来,它都只是一个长长的字节流。
-
结构: 文件内部没有结构。任何结构和意义都由访问该文件的应用程序来解释和管理。例如,文本编辑器知道换行符
\n
的含义,而编译器知道.c
文件中main()
函数的语法结构,但操作系统本身对此一无所知。 -
访问方式: 基本的访问单位是字节。可以通过一个读写指针来顺序地访问文件,也可以通过
lseek
等操作将指针移动到任意字节位置,实现随机访问。 -
典型例子: 所有在UNIX/Linux和Windows中的文件,本质上都是流式文件。例如
.txt
,.c
,.jpg
,.mp3
,.exe
等。
2. 有结构文件 (记录式文件 - Record-based File)
在这种结构中,文件不再是无差别的字节流,而是由一组具有相似结构的记录 (Record) 构成的集合。一条记录通常用于描述一个实体对象的信息。
-
核心思想: 文件是记录的序列,操作系统需要理解“记录”是文件的基本组成单位。
-
结构:
-
定长记录: 文件中所有记录的长度都是相同的。这种结构简单,易于管理。要访问第
i
条记录,可以直接计算其地址:地址 = i * 单条记录长度
。这使得随机访问非常高效。 -
变长记录: 文件中各条记录的长度可以不同。这种结构存储效率高,不浪费空间,但管理复杂,实现随机访问的难度较大,通常需要在每条记录的开头存储其长度信息。
-
-
访问方式: 基本的访问单位是记录。
-
典型例子: 这种结构在早期的操作系统(如大型机的文件管理系统)和某些特定的商业应用(如COBOL语言处理的文件、数据库文件)中比较常见。
索引文件 (Indexed File) 是什么?
现在,我们来重点讲解“索引文件”。索引文件是“有结构文件”的一种高级、复杂且高效的组织形式,其设计的核心目的就是为了解决对文件中记录的快速随机访问问题。
1. 核心思想与类比
想象一本非常厚的书,如果你想找一个特定的知识点,从第一页翻到最后一页会非常慢。你会怎么做?你会去翻书最后的索引。索引告诉你“某个关键词在第几页”,然后你直接翻到那一页即可。
索引文件就是采用了完全相同的思想。
2. 结构组成
一个索引文件通常由两部分构成:
-
数据文件 (Data File): 存放着所有的实际记录。这些记录可以顺序存放,也可以无序存放。
-
索引表 (Index Table): 这是索引文件的精华所在。它是一张独立的、通常比数据文件小得多的表。表中的每一项都是一个索引项。
-
索引项的结构:
(关键字, 指针)
-
关键字 (Key): 是记录中的某个数据项,用于唯一标识这条记录。例如,在一个学生信息文件中,关键字可以是“学号”。
-
指针 (Pointer): 指向该关键字对应的记录在数据文件中的存储地址(可以是逻辑记录号或物理地址)。
-
-
3. 工作流程(如何访问)
假设我们要查找学号为“20250702”
的学生记录:
-
不读数据文件: 程序不会去遍历庞大的学生数据文件。
-
查找索引表: 程序会直接在索引表中查找关键字
“20250702”
。由于索引表通常是按关键字排好序的,所以可以使用二分查找等高效算法,查找速度非常快。 -
获取指针: 在索引表中找到该关键字后,从中取出与之对应的指针(例如,指针告诉我们该记录是数据文件中的第158条记录)。
-
直接访问数据: 程序利用这个指针,直接计算出第158条记录在数据文件中的确切位置,并将其读入内存。
4. 图示理解
索引表 (Index Table) 数据文件 (Data File)
+----------------+---------+ +--------------------------------+
| 关键字(Key) | 指针 | | 记录1 (Record 1) |
+----------------+---------+ +--------------------------------+
| “20250001” | 1 | -- 指向 --> | 记录2 (Record 2) |
+----------------+---------+ +--------------------------------+
| “20250002” | 2 | | ... |
+----------------+---------+ +--------------------------------+
| ... | ... | | 记录158 (学号为“20250702”) | <--+
+----------------+---------+ +--------------------------------+ |
| “20250702” | 158 | -----------------------------------------------------+
+----------------+---------+ | ... |
| ... | ... | +--------------------------------+
+----------------+---------+