根目录(或称 根文件夹 Root folder,或称 根目录项)位于FAT32分区的数据区起始位置(紧接在FAT1和FAT2表之后)。
详见:
https://www.softool.cn/read/a250716/2507161059.html 卷组织结构图。
每个根目录占用32B
(下面的表14),根目录描述根分区中的文件和文件夹。
FAT32根目录结构的结构分为2种:短文件格式和长文件格式。
短文件格式
- 对于短文件名,系统将文件名分成两部分进行存储,即 主文件名+扩展名。
- 0x0~0x7字节记录文件的主文件名;
- 0x8~0xA记录文件的扩展名,取文件名中的ASCII码值;
- 不记录主文件名与扩展名之间的”.”;
- 主文件名不足 8 个字符以空白符(20H)填充,扩展名不足 3 个字符同样以空白符(20H)填充;
- 0x00 偏移处的取值若为 00H,表明目录项为空;若为E5H,表明目录项曾被使用,但对应的文件或文件夹已被删除。(这也是误删除后恢复的理论依据)。
- 文件名中的第一个字符若为“.”或“..”表示这个簇记录的是一个子目录的目录项。“.”代表当前目录;“..”代表上级目录。
0xB为
属性
字段
可以看作系统将 0xB 的一个字节分成 8 位,用其中的一位代表某种属性的有或无。
如 00000101 就表示这是个文件,属性是只读、系统。
bit[4] = 1 表示目录
bit[4] = 0 表示文件0x0E~0x0F为文件 创建时间 字段
Bit 0~4:为文件创建时间字段秒/2的值;
Bit 5~10:为文件创建时间字段分钟的值;
Bit 11~15:为文件创建时间字段小时的值;0x10~0x11文件 创建日期 字段
Bit 0~4:为文件创建日期字段日期数的值;
Bit 5~8:为文件创建日期字段月份的值;
Bit 9~15:为文件创建时间字段年号-1980的值
SofTool.CN:
Bit 9~15:为文件创建时间字段年号-1980的值 的理解:
Bit 9~15(共7个二进制位)组合成一个无符号整数,表示 文件创建年份与基准年(1980)的差值。
计算公式:
文件实际创建年份 = (Bit 9~15表示的数值) + 1980
所以此时的年份位最大可以到:127+1980=2107年。
结论:FAT文件系统的原生日期字段确实在2107年后失效。这是早期设计的历史局限性,现代系统已通过扩展字段或新文件系统(如exFAT)解决该问题。如需长期兼容,建议避免使用纯FAT格式存储关键数据。
0x14~0x15 文件起始簇号的高16位, 0x1A~0x1B 文件起始簇号的低16位
它存放文件或目录的起始簇号,系统根据该起始簇号在FAT表(FAT1或FAT2)中找到数据的入口,然后再跟踪 簇链 直至 簇尾,同时用 0x1C~0x1F处字节判定有效性。就可以完全无误的读取文件(或目录)了。普通子目录的寻址过程也是通过其父目录中的目录项来指定的,与数据文件(指非目录文件)不同的是目录偏移 0xB的第4位置 1,而数据文件为0。
具体FAT32短文件格式表格如下:
长文件格式
FAT32 的一个重要的特点是完全支持长文件名。长文件名依然是记录在目录项中的。
为了低版本的 OS 或程序能正确读取长文件名文件,系统自动为所有长文件名文件创建了一个对应的短文件名,使对应数据既可以用长文件名寻址,也可以用短文件名寻址。
不支持长文件名的 OS 或程序会忽略它认为不合法的长文件名字段,而支持长文件名的 OS 或程序则会以长文件名为显式项来记录和编辑,并隐藏起短文件名。
当创建一个长文件名文件时,系统会自动加上对应的短文件名,其一般有的原则:
- 取长文件名的前 6 个字符加上”~1”形成短文件名,扩展名不变。
- 如果已存在这个文件名,则符号”~“后的数字递增,直到5。
- 如果文件名中”~“后面的数字达到 5,则短文件名只使用长文件名的前两个字母。
通过数学操纵长文件名的剩余字母生成短文件名的后四个字母,然后加后缀”~1”直到最后。 - 如果存在老 OS 或程序无法读取的字符,换以”_”
长文件名的实现有赖于目录项偏移为 0xB 的属性字节,当此字节的属性为:只读、隐藏、系统、卷标,即其值为 0FH 时,DOS 和 WIN32 会认为其不合法而忽略其存在。系统将长文件名以 13 个字符为单位进行切割,每一组占据一个目录项。所以可能一个文件需要多个目录项,这时长文件名的 各个目录项按倒序排列在目录表中,以防与其他文件名混淆。长文件名中的字符采用 unicode 形式编码,每个字符占据 2 字节的空间。
NOTE:系统在存储长文件名时,总是先按倒序填充长文件名目录项,然后紧跟其对应的短文件名。从以上的表格可以看出,长文件名中并不存储对应文件的文件开始簇、文件大小、各种时间和日期属性。文件的这些属性还是存放在短文件名目录项中,一个长文件名总是和其相应的短文件名一 一对应,短文件名没有了长文件名还可以读,但长文件名如果没有对应的短文件名,不管什么系统都将忽略其存在。所以短文件名是至关重要的。
下面的截图为SD卡根目录(Root folder)实例解析:
举例
下面通过实例文件夹:System Volume Information来解析里面的数据,如下:
通过上面实例表格了解到重要信息总结如下:
- 文件名称和属性
文件名:System Volume Information
属性:目录、系统、隐藏 - 文件创建时间
文件创建时间的值为0xAA7D,按照前面介绍的公式解析时间为21:19:58,解析过程如下: - 文件创建日期
文件创建时间的值为0x5276,按照前面介绍的公式解析时间为2021/03/22,解析过程如下: - 文件起始簇号
文件起始簇号的值的来源:0x54~0x55(0x0000)作为高16位, 0x5A~0x5B(0x0003)作为低16位。最终文件起始簇号的值为 0x00000003 ,说明该文件的起始地址为:文件地址 = 根目录开始地址 + ((起始簇号 - 根目录簇号(Root Cluster Number)) * 每簇扇区数(Sectors Per Cluster) * 扇区字节数(Bytes Per Sector))
文件地址 = 0x1000000 + ((3 - 2) * 32 * 512) = 0x1004000 Bytes
经过计算可以得到文件起始存放位置在0x1004000,然后验证果然在该位置找到了文件夹:System Volume Information存放的数据,如下: