錯誤信息
System.IO.PathTooLongException:“指定的路徑或文件名太長,或者兩者都太長。完全限定文件名必須少於 260 個字符,並且目錄名必須少於 248 個字符。”
環境
NET 4.5
原因分析
在C#API中讀取文件或文件夾時,完全限定文件名必須少於 260 個字符,並且目錄名必須少於 248 個字符。(System.IO
源碼中做的限制)
解決方案
方案1
使用第三方開源庫ZetaLongPaths ,NuGet中使用1.0.0.24的版本,更高版本需要 NET 4.5.2 框架。
功能:
- ZlpFileInfo- 類似於
System.IO.FileInfo
的類,它包裝函數以處理文件路徑。 - ZlpDirectoryInfo- 類似於
System.IO.DirectoryInfo
的類,它包裝函數以處理文件夾路徑。 - ZlpIOHelper-一組靜態函數,以提供類似的功能,作為ZlpFileInfo與ZlpDirectoryInfo類,但在靜態上下文。
- ZlpPathHelper- 一組類似於
System.IO.Path
的靜態函數,用於路徑。
使用
代碼示例及比較
ZetaLongPaths.ZlpPathHelper.Combine(Path, tpName);
//System.IO.Path.Combine(Path, tpName);
ZetaLongPaths.ZlpPathHelper.Combine(null, null, null, names.ToArray());
//System.IO.Path.Combine(names.ToArray());
ZetaLongPaths.ZlpIOHelper.GetFiles(dirpath, "*");
//System.IO.Directory.GetFiles(dirpath, "*.*");
ZetaLongPaths.ZlpPathHelper.GetFileNameWithoutExtension(mDir);
//System.IO.Path.GetFileNameWithoutExtension(m_Dir);
ZetaLongPaths.ZlpIOHelper.DeleteFile(filePath);
//System.IO.File.Delete(filePath);
var directory = new ZlpDirectoryInfo(dirPath);
//var directory = new DirectoryInfo(dirPath);
ZetaLongPaths.ZlpPathHelper.GetDirectoryPathNameFromFilePath(path);
//System.IO.Path.GetDirectoryName(path);
ZetaLongPaths.ZlpIOHelper.DirectoryExists(folderPath);
//System.IO.Directory.Exists(folderPath);
ZetaLongPaths.ZlpIOHelper.CreateDirectory(folderPath);
//Directory.CreateDirectory(folderPath);
優點
- 能滿足大部分文件和文件夾的操作
- 輕量(65KB)
缺點
- 同
System.IO
的接口規范有不小的區別,使用時需要逐個確認並替換 - 缺少對文件流(
System.IO.File
)的相關操作的支持,例如使用File.Open(string path, FileMode mode)
或者new FileStream(string path, FileMode mode)
類型時,還是會因為文件名長度問題,報長度或者其他異常。
方案2
使用第三方開源庫AlphaFS,它為.NET平台提供比標准System.IO
類更完整的Win32文件系統功能支持的功能。
功能
- 支持擴展長度路徑(最長32000個字符)
- 創建連接點/硬鏈接
- 訪問隱藏的卷
- 卷的枚舉
- 事務性文件操作
- 支持NTFS備用數據流(文件/文件夾)
- 訪問網絡資源(SMB / DFS)
- 創建和訪問名稱中包含前導/尾隨空格的文件夾/文件
- 支持自定義篩選和錯誤報告/恢復的文件夾/文件枚舉器(訪問被拒絕的例外)
優點
Alphaleonis.Win32.Filesystem
的類名以及接口很規范,能夠無縫替換System.IO
- 功能全面強大
缺點
庫比較大(359KB)
方案3
使用“\\?\”作為文件名前綴並調用Windows API的Unicode版本
方案4
升級框架NET 4.6.2及其以上版本以解決上述bug