在NTFS中,我可以用\?
字符序列作为路径的前缀,表示它是一个超过260个字符限制的路径;这样,文件系统将正确解释路径并避免引发PathTooLongException
。
(详见http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx#maxpath)
是否有一个。net API,将前缀我的路径字符串与这个序列,或者我坚持写我自己的?
在本质上,我正在寻找一个方法,相当于以下。
static string ToExtendedPath(string path)
{
if(Path.IsPathRooted(path))
{
return @"\?" + path;
}
return Path.Combine(@"\?", path);
}
不,没有。net API可以将给定的"正常"路径转换为扩展语法。您必须自己滚动(顺便说一下,这是微不足道的)。
请注意:正如Cody Gray和Hans Passant所提到的,. net框架不支持长(扩展)路径。如果你想使用它们,你需要直接使用API。也不是所有的API函数都支持长路径。一般来说,低级函数可以。请参阅MSDN文档。
我所做的是为相关的API函数(例如CreateFile)编写包装器函数,并调用这些包装器而不是。net文件系统函数。
正如@ helange -klein指出的那样,没有。net API可以解决260个字符的限制,该功能完全依赖于操作系统,其中一些支持基于注册表的260个max_path限制的覆盖。
[编辑]DotNet 4.6.2以后的支持:System.IO。LongPath, Blog and sample
Windows 10 Creators Update扩展了内核(和命令提示符),使其具有MoveFileExW,但正如dotnetReferenceSource中明显的那样,扩展内核的使用不包括在DotNet Framework System.IO.File:
#if FEATURE_CORESYSTEM
[DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
[ResourceExposure(ResourceScope.Machine)]
private static extern bool MoveFileEx(String src, String dst, uint flags);
internal static bool MoveFile(String src, String dst)
{
return MoveFileEx(src, dst, 2 /* MOVEFILE_COPY_ALLOWED */);
}
#else // FEATURE_CORESYSTEM
[DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
[ResourceExposure(ResourceScope.Machine)]
internal static extern bool MoveFile(String src, String dst);
#endif // FEATURE_CORESYSTEM
一个LinqPad程序的例子来包装MoveFile(其他可以在pinvoke上找到)
void Main()
{
//Create 3 files: in c:temptest
//testsrc0.txt, testsrc1.txt and testsrc2.txt
//"\?UNCservershare",
string src0File = @"\?UNC127.0.0.1c$temptesttestsrc0.txt";
string dst0File = @"\?UNC127.0.0.1c$temptesttestdst0.txt";
string dst0FileDotNet = @"c:temptesttestdst0.txt";
string src1File = @"\?c:temptesttestsrc1.txt";
string dst1File = @"\?c:temptesttestdst1.txt";
string dst1FileDotNet = @"c:temptesttestdst1.txt";
string src2File = @"\?\127.0.0.1c$temptesttestsrc2.txt";
string dst2File = @"\?\127.0.0.1c$temptesttestdst2.txt";
string dst2FileDotNet = @"c:temptesttestdst2.txt";
MoveFileEx(src0File, dst0File, MoveFileFlags.MOVEFILE_REPLACE_EXISTING);
System.IO.File.Exists(dst0File).Dump("File0 Exists");//FALSE
System.IO.File.Exists(dst0FileDotNet).Dump("File0 Exists");//TRUE
MoveFileEx(src1File, dst1File, MoveFileFlags.MOVEFILE_REPLACE_EXISTING);
System.IO.File.Exists(dst1File).Dump("File1 Exists");//FALSE
System.IO.File.Exists(dst1FileDotNet).Dump("File1 Exists");//TRUE
MoveFileEx(src2File, dst2File, MoveFileFlags.MOVEFILE_REPLACE_EXISTING);
System.IO.File.Exists(dst2File).Dump("File2 Exists");//FALSE
System.IO.File.Exists(dst2FileDotNet).Dump("File2 Exists");//FALSE - as missing UNC keyword
System.Runtime.InteropServices.Marshal.GetLastWin32Error().Dump("ERROR:");//3 == ERROR_PATH_NOT_FOUND
}
[Flags]
enum MoveFileFlags
{
MOVEFILE_REPLACE_EXISTING = 0x00000001,
MOVEFILE_COPY_ALLOWED = 0x00000002,
MOVEFILE_DELAY_UNTIL_REBOOT = 0x00000004,
MOVEFILE_WRITE_THROUGH = 0x00000008,
MOVEFILE_CREATE_HARDLINK = 0x00000010,
MOVEFILE_FAIL_IF_NOT_TRACKABLE = 0x00000020
}
// Define other methods and classes here
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, MoveFileFlags dwFlags);
包含驱动器和UNC路径的路径需要键入关键字"UNC"。?div UNC