文档库 最新最全的文档下载
当前位置:文档库 › FAT32长文件名实现

FAT32长文件名实现

FAT32长文件名实现
FAT32长文件名实现

================

英文版长文件名实现

================

先用实例说明:在CF卡上保存一个名为“longname12345678901234567890.txt”的英文长文件名文件,用WinHEX读

取盘片目录扇区,得到如下数据:

0 1 2 3 4 5 6 7 8 9 A B C D E F

------------------------------------------------

43 39 00 30 00 2E 00 74 00 78 00 0F 00 F4 74 00 | C9.0...t.x...魌.

00 00 FF FF FF FF FF FF FF FF 00 00 FF FF FF FF | ..

02 36 00 37 00 38 00 39 00 30 00 0F 00 F4 31 00 | .6.7.8.9.0...?..

32 00 33 00 34 00 35 00 36 00 00 00 37 00 38 00 | 2.3.4.5.6...7.8.

01 6C 00 6F 00 6E 00 67 00 6E 00 0F 00 F4 61 00 | .l.o.n.g.n...鬭.

6D 00 65 00 31 00 32 00 33 00 00 00 34 00 35 00 | m.e.1.2.3...4.5.

4C 4F 4E 47 4E 41 7E 31 54 58 54 20 00 07 D6 99 | LONGNA~1TXT ..謾

58 39 58 39 00 00 D7 99 58 39 00 00 00 00 00 00 | X9X9..讬X9......

你会发现长文件名是倒着排放的(每目录项存13个字节文件名),最下面是短文件名LONGNA~1TXT

FAT32的一个重要的特点是完全支持长文件名。长文件名依然是记录在目录项中的。为了低版本的OS或程序能正确

读取长文件名文件,系统自动为所有长文件名文件创建了一个对应的短文件名,使对应数据既可以用长文件名寻址,

也可以用短文件名寻址。不支持长文件名的OS或程序会忽略它认为不合法的长文件名字段,而支持长文件名的OS或

程序则会以长文件名为显式项来记录和编辑,并隐藏起短文件名。

当创建一个长文件名文件时,系统会自动加上对应的短文件名,其一般有的原则:

(1)、取长文件名的前6个字符加上"~1"形成短文件名,扩展名不变。

(2)、如果已存在这个文件名,则符号"~"后的数字递增,直到5。

(3)、如果文件名中"~"后面的数字达到5,则短文件名只使用长文件名的前两个字母。通过数学操纵长文件名的剩

余字母生成短文件名的后四个字母,然后加后缀"~1"直到最后(如果有必要,或是其他数字以避免重复的文件名)。

(4)、如果存在老OS或程序无法读取的字符,换以"_"

长文件名的实现有赖于目录项偏移为0xB的属性字节,当此字节的属性为:只读、隐藏、系统、卷标,即其值为0FH

时,DOS和WIN32会认为其不合法而忽略其存在。这正是长文件名存在的依据。将目录项的0xB置为0F,其他就任由

系统定义了,Windows9x或Windows 2000、XP通常支持不超过255个字符的长文件名。

系统将长文件名以13个字符为

单位进行切割,每一组占据一个目录项。所以可能一个文件需要多个目录项,这时长文件名的各个目录项按倒序排

列在目录表中,以防与其他文件名混淆。长文件名中的字符采用unicode形式编码,每个字符占据2字节的空间。

系统在存储长文件名时,总是先按倒序填充长文件名目录项,然后紧跟其对应的短文件名。从表2可以看出,长文件

名中并不存储对应文件的文件开始簇、文件大小、各种时间和日期属性。文件的这些属性还是存放在短文件名目录项

中,一个长文件名总是和其相应的短文件名一一对应,短文件名没有了长文件名还可以读,但长文件名如果没有对应

的短文件名,不管什么系统都将忽略其存在。所以短文件名是至关重要的。在不支持长文件名的环境中对短文件名中

的文件名和扩展名字段作更改(包括删除,因为删除是对首字符改写E5H),都会使长文件名形同虚设。长文件名和短

文件名之间的联系光靠他们之间的位置关系维系显然远远不够。其实,长文件名的0xD 字节的校验和起很重要的作用,

此校验和是用短文件名的11个字符通过一种运算方式来得到的。系统根据相应的算法来确定相应的长文件名和短文件

名是否匹配。这个算法不太容易用公式说明,我们用一段c程序来加以说明。

假设文件名11个字符组成字符串shortname[],校验和用chknum表示。得到过程如下:

int i,j,chknum=0;

for (i=11; i>0; i--)

chksum = ((chksum & 1) ? 0x80 : 0) + (chksum >> 1) + shortname[j++];

如果通过短文件名计算出来的校验和与长文件名中的0xD偏移处数据不相等。系统无论如何都不会将它们配对的。

-----------------------------------------------------

| 表1 FAT32短文件目录项32个字节的表示定义 |

-----------------------------------------------------

|字节偏移(16进制) | 字节数 | 定义 |

-----------------------------------------------------

| 0x0~0x7 | 8 | 文件名 |

-----------------------------------------------------

| 0x8~0xA | 3 | 扩展名 |

-----------------------------------------------------

| | | | 00000000(读写) |

| | | | 00000001(只读) |

| | | 属| 00000010(隐藏) |

| 0xB* | 1 | 性| 00000100(系统) |

| | | 字| 00001000(卷标) |

| | | 节| 00010000(子目录) |

| | | | 00100000(归档) |

-----------------------------------------------------

| 0xC | 1 | 系统保留 |

-----------------------------------------------------

| 0xD | 1 | 创建时间的10毫秒位 |

-----------------------------------------------------

| 0xE~0xF | 2 | 文件创建时间 |

-----------------------------------------------------

| 0x10~0x11 | 2 | 文件创建日期 |

| 0x12~0x13 | 2 | 文件最后访问日期 |

| 0x14~0x15 | 2 | 文件起始簇号的高16位 |

| 0x16~0x17 | 2 | 文件的最近修改时间 |

| 0x18~0x19 | 2 | 文件的最近修改日期 |

| 0x1A~0x1B | 2 | 文件起始簇号的低16位 |

| 0x1C~0x1F | 4 | 表示文件的长度 |

-----------------------------------------------------

*此字段在短文件目录项中不可取值0FH,如果设值为0FH,目录段为长文件名目录段

------------------------------------------------------

| 表2 FAT32长文件目录项32个字节的表示定义 |

------------------------------------------------------

| 字节偏移 | 字节数| 定义|

| (16进制) | | |

------------------------------------------------------

| | | | 7 保留未用|

| | | 属| 6 1表示长文件最后一个目录项|

| | | 性| 5 保留未用|

| | | 字| 4 |

| 0x0 | 1 | 节| 3 |

| | | 位| 2 顺序号数值|

| | | 意| 1 |

| | | 义| 0 |

------------------------------------------------------

| 0x1~0xA | 10 | 长文件名unicode码|

| 0xB | 1 | 长文件名目录项标志,取值0FH |

| 0xC | 1 | 系统保留 |

| 0xD | 1 | 校验值(根据短文件名计算得出) |

| 0xE~0x19 | 12 | 长文件名unicode码|

| 0x1A~0x1B | 2 | 文件起始簇号(目前常置0) |

| 0x1C~0x1F | 4 | 长文件名unicode码|

------------------------------------------------------

只要按照上述格式保存长文件名目录项,就可以实现长文件名了,需要修改的部分是打开、删除、改名等文件

系统函数。先生成若干长文件名目录项,倒序排列,计算校验和,填写序号,设置0F 标志,UNICODE转换,

设置最后目录项,填充FF结束。然后,按要求生成短文件名目录项。

====================

简体中文版长文件名实现

====================

上面的方法可以实现英文长文件名,但如果想支持简体中文,还需要支持GB和UNICODE 互换,ASCII和GB混排。

---------------

GB和UNICODE互换

---------------

UNICODE转GB和GB转UNICODE没什么好办法,一般通过查表法实现。

unsigned short int unigb_table[7446][2]={

0x00a4,0xa1e8,

0x00a7,0xa1ec,

0x00a8,0xa1a7,

0x00b0,0xa1e3,

0x00b1,0xa1c0,

......

0xffe0,0xa1e9,

0xffe1,0xa1ea,

0xffe3,0xa3fe,

0xffe5,0xa3a4,

0xffff,0x0000

};

上面的表格是按UNICODE增序排列的UNICODE编码到GB编码转换对照表。因为该表为顺序表,所以可以采用二分查表法

大大加快查询速度。没办法,这个表就是有点大,如果不需要支持简体中文,最好把它配置裁减掉,以便节省存储空

间。

将上表反过来就可以实现GB编码到UNICODE编码转换对照表gbuni_table[7446][2]。一个小技巧:直接用EXCEL打开

unigb_table数据部分,选择逗号做分割符,交换两列位置,按GB码增序排序,然后再插入两列,输入逗号,拖下去,

产生两列逗号,保存之,再稍加修改即可生成增序排列的GB编码到UNICODE编码转换对照表。

相关文档