Windows 平台上长路径名文件的解决方法

来源:互联网 发布:自动化测试 知乎 编辑:程序博客网 时间:2024/04/28 11:56

在 C/C++ 中使用超过 260 个字符的路径长度的文件,会复杂得多。下面介绍两种支持长路径名文件的方法。

从微软官方网站 Path Field Limits,可以查到,使用 Unicode 版本的 API,对于使用 NTFS 文件系统的 Windows NT 4.0, Windows 2000, Windows XP Home Edition, Windows XP Professional 和 Windows Server 2003 操作系统,可以支持 32768 字节的文件路径长度。同时,路径名必须使用 \\?\ 的前缀。依照这个思路,我们设计了实验。


                {FILE *from, *to;char filename[1024];strcpy(filename,"\\\\?\\E:\\VerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpath\\VerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpath.txt");int iL1=MultiByteToWideChar(CP_ACP, 0, filename, strlen(filename), NULL, 0); WCHAR* wfilename=new WCHAR[iL1+1]; wfilename[iL1] = '\0';int iL2=MultiByteToWideChar(CP_ACP, 0, filename, strlen(filename), wfilename, iL1); from = _wfopen( wfilename ,L"rb");to = fopen(".\\longpath.txt", "wb");if((from ==NULL)||(to==NULL))    return -1;char buffer[1024];int count = 0;while ( (count = fread(buffer, sizeof(char), 1024, from)) != 0)    fwrite( buffer, sizeof(char), count, to);delete []wfilename;fclose (from); fclose(to);}

使用如上的方法,我们可以拷贝某长路径名的文件到当前文件夹中。从试验结果看,该方法是有效的。但是,由于该方法要求系统使用 Unicode 的 API,同时需要更改路径名称以及编码方式。因此,对于一个已经存在的系统,由于需要改变所有文件操作相关的 API,因此改动将会很大。

对于每一个长路径名,都有一个 8.3 格式(8 个字符的文件名和 3 个字符的后缀名)的短路径名与其相对应,任意的文件夹或者文件名都可以映射成一个 8 字符的文件名(A~B),其中 A 是文件名前缀,B 是表示字母序的顺序。操作系统可以保证这样的映射是一对一的,只要使用GetShortPathName() 将长路径名转成相应的短路径名,就可以进行对该文件进行普通的文件操作。同时,在任何时候都可以用函数GetLongPathName() 把 8.3 格式的短路径名恢复成初始的长路径名。

如 GetShortPathName Function 叙述,我们需要一个 Unicode 版本的 API,同时在路径名前加上 \\?\ 的前缀,才能实现长短路径名间的切换。但从实验来看,即使不使用 Unicode 的 API,依然可以实现上述功能。

                {char pathName [1024];strcpy(pathName,"\\\\?\\E:\\VerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpath\\VerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpathVerylongpath.txt");const int MaxPathLength = 2048;char shortPath[MaxPathLength];if (strlen(pathName) >= MAX_PATH){    char prePath[] = "\\\\?\\";    if (strlen(pathName) >= MaxPathLength - strlen(pathName))        return false;    sprintf(shortPath, "%s%s", prePath, pathName);    for (int iPathIndex = 0; iPathIndex < strlen(shortPath); iPathIndex++)        if (shortPath[iPathIndex] == '/')            shortPath[iPathIndex] = '\\';    int dwlen = GetShortPathName(shortPath, shortPath, MaxPathLength);    if (dwlen <= 0)        return false;}}

经过上述的代码,超过 MAX_PATH 限制的路径名都可以转变成一个 8.3 格式的短路径名,可以把这个文件名 (shortPath)作为后续文件操作函数的参数。这种情况下,对于该文件的所有操作都可以被支持了。我们用这种缩短路径名长度的方式解决了长路径名文件的操作问题。

参考:

http://www.chineselinuxuniversity.net/articles/9402.shtml