我目前正在使用以下P / Invoke签名来获取常规Windows文件的短文件名:
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetShortPathName([MarshalAs(UnmanagedType.LPTStr)] string path,
[MarshalAs(UnmanagedType.LPTStr)] StringBuilder shortPath,
int shortPathLength);
目前 - 它没有任何问题,但我发现了一些相当特殊的东西:
我知道Windows使用以下短文件名约定:
将名称剪切为6个字符(不带扩展名)
附加代字号(~
)
附加一个无符号整数,表示匹配索引(从1开始)
附加原始文件扩展名
因此,文件名C:\abcdefghijklmn.txt
应该可以在短名称C:\abcdefg~1.txt
下访问。 (工作正常。)
现在奇怪的部分:我最近在音乐目录中对特定的音频文件进行了一次小搜索。这就是结果:
.\Rammstein & Tatu - Moscow.mp3
.\Rammstein - Asche zu Asche.mp3
.\Rammstein - Der Meister.mp3
.\Rammstein - Du Hast.mp3
.\Rammstein - Eifersucht.mp3
.\Rammstein - Feuer Frei.mp3
.\Rammstein - Führe Mich.mp3
.\Rammstein - Haifisch.mp3
...
用简短的表示法进行相同的搜索:
.\RA8E17~1.MP3
.\RA23A6~1.MP3
.\RAMMST~1.MP3
.\RA0CAE~1.MP3
.\RAMMST~2.MP3
.\RAMMST~3.MP3
.\RAMMST~4.MP3
.\RA6BAA~1.MP3
...
我的问题是:为什么Windows会在代字号之前生成这样的“随机”前缀(例如RA23A6
或RA0CAE
)?
答案 0 :(得分:9)
微软没有记录这一点,但维基百科确实如此:
虽然没有从LFN创建8.3名称的强制算法,但Windows使用以下约定:
1.如果LFN为8.3大写,则根本不会在磁盘上存储LFN。
- 示例:
TEXTFILE.TXT
2.如果LFN是8.3混合大小写,则LFN将存储混合大小写的名称,而8.3名称将是大写的版本。
- 示例:
TextFile.Txt
变为TEXTFILE.TXT
。
3.如果文件名包含8.3名称中不允许的字符(包括不按惯例禁止的空间,但不包括API)或者任何一部分太长,则该名称将被删除无效字符,例如空格和额外句点。其他字符(例如
+
)更改为下划线_
和大写字母。然后将被剥离的名称截断为其基本名称的前6个字母,后跟一个代字号,后跟一个数字,后跟句点.
,后跟扩展名的前3个字符。
- 示例:
TextFile1.Mine.txt
变为TEXTFI~1.TXT
(或TEXTFI~2.TXT
,TEXTFI~1.TXT
已存在)。ver +1.2.text
变为VER_12~1.TEX
。
4. 从Windows 2000开始,如果已经存在至少4个文件或文件夹,其短名称中包含相同的初始6个字符,则剥离的LFN将被截断为基本名称的前2个字母(或1)如果basename只有1个字母),则后跟4个十六进制数字,这些数字来自文件名的未记录的散列,后跟一个代字号,后跟一个数字,后跟一个句点
.
,后跟前3个字符扩展名。
- 示例:
TextFile.Mine.txt
变为TE021F~1.TXT
。
正如Joey所说,文件名的未记录的哈希值为reverse engineered。
答案 1 :(得分:3)
这是因为使用计数器和前缀的非常原始的方案只能使用一定数量的文件。随着越来越多的文件,Windows切换到更短的前缀和哈希。 Someone actually reverse-engineered the hash以及一些解释:
如果你不知道8.3文件名是如何工作的,这里很快 破落。
- 除了将文件名与扩展名分开的所有句点都被删除 - a.testing.file.bat变为 atestingfile.bat。
- 某些特殊字符(如+)会变成下划线,其他字符会被删除。文件名是大写的。 1 + 2 + 3您好 World.exe变为1_2_3HELLOWORLD.EXE。
- 文件扩展名被截断为3个字符,并且(如果长度超过8个字符)文件名被截断为6个字符 ~1。 SomeStuff.aspx变成了SOMEST~1.ASP。
- 如果这些会导致碰撞,则使用~2,然后使用~3和~4。
- 而不是转到~5,文件名被截断为2个字符,替换为十六进制校验和 长文件名 - SomeStuff.aspx变成SOBC84~1.ASP,其中BC84 是(以前)未记录的校验和函数的结果。