解决文件路径过长异常的最佳方法

时间:2012-01-05 15:39:57

标签: c# .net string file sharepoint

我创建了一个应用程序,可以下载SP站点中的所有文档库,但有一次它给了我这个错误(我试着看谷歌但不能找到任何东西,现在如果有人知道任何解决这个问题的技巧请否则,谢谢你的回答)

  

System.IO.PathTooLongException:指定的路径,文件名或两者都太长。完全限定的文件名必须少于260个字符,目录名必须少于248个字符。      在System.IO.Path.NormalizePathFast(String path,Boolean fullCheck)      在System.IO.Path.GetFullPathInternal(String path)      at System.IO.FileStream.Init(String path,FileMode mode,FileAccess access,Int32 rights,Boolean useRights,FileShare share,Int32 bufferSize,FileOptions options,SECURITY_ATTRIBUTES secAttrs,String msgPath,Boolean bFromProxy)      在System.IO.FileStream..ctor(字符串路径,FileMode模式,FileAccess访问,FileShare共享,Int32 bufferSize,FileOptions选项)      在System.IO.File.Create(String path)

它达到字符串的限制,代码如下,

#region Downloading Schemes

    private void btnDownload_Click(object sender, EventArgs e)
    {
        TreeNode currentNode = tvWebs.SelectedNode;
        SPObjectData objectData = (SPObjectData)currentNode.Tag;
        try
        {
            CreateLoggingFile();
            using (SPWeb TopLevelWeb = objectData.Web)
            {
                if(TopLevelWeb != null)
                    dwnEachWeb(TopLevelWeb, TopLevelWeb.Title, tbDirectory.Text);
            }
        }
        catch (Exception ex)
        {
            Trace.WriteLine(string.Format("Exception caught when tried to pass TopLevelWeb:{1}, Title = {2}, object data to (dwnEachWeb_method), Exception: {0}", ex.ToString(), objectData.Web, objectData.Title));
        }
        finally
        {
            CloseLoggingFile();
        }
    }

    private void dwnEachWeb(SPWeb TopLevelWeb, string FolderName, string CurrentDirectory)
    {
        if (TopLevelWeb != null)
        {
            if (TopLevelWeb.Webs != null)
            {
                CurrentDirectory = CurrentDirectory + "\\" + TopLevelWeb.Title;
                CreateFolder(CurrentDirectory);
                foreach (SPWeb ChildWeb in TopLevelWeb.Webs)
                {

                    dwnEachWeb(ChildWeb, ChildWeb.Title, CurrentDirectory);
                    ChildWeb.Dispose();
                }
                dwnEachList(TopLevelWeb, CurrentDirectory);
                //dwnEachList(TopLevelWeb, FolderName, CurrentDirectory);
            }
        }
    }

    private void dwnEachList(SPWeb oWeb, string CurrentDirectory)
    {
        foreach (SPList oList in oWeb.Lists)
        {
            if (oList is SPDocumentLibrary && !oList.Hidden)
            {
                dwnEachFile(oList.RootFolder, CurrentDirectory);
            }
        }
    }

    private void dwnEachFile(SPFolder oFolder, string CurrentDirectory)
    {
        if (oFolder.Files.Count != 0)
        {
            CurrentDirectory = CurrentDirectory + "\\" + oFolder.Name;
            CreateFolder(CurrentDirectory);
            foreach (SPFile ofile in oFolder.Files)
            {
                if (CreateDirectoryStructure(CurrentDirectory, ofile.Url))
                {
                    var filepath = System.IO.Path.Combine(CurrentDirectory, ofile.Url);
                    byte[] binFile = ofile.OpenBinary();
                    System.IO.FileStream fstream = System.IO.File.Create(filepath);
                    fstream.Write(binFile, 0, binFile.Length);
                    fstream.Close();
                }
            }
        }
    }

    //creating directory where files will be download        
    private bool CreateDirectoryStructure(string baseFolder, string filepath)
    {
        if (!Directory.Exists(baseFolder)) return false;

        var paths = filepath.Split('/');

        for (var i = 0; i < paths.Length - 1; i++)
        {
            baseFolder = System.IO.Path.Combine(baseFolder, paths[i]);
            Directory.CreateDirectory(baseFolder);
        }
        return true;
    }

    //creating folders
    private bool CreateFolder(string CurrentDirectory)
    {
        if (!Directory.Exists(CurrentDirectory))
        {
            Directory.CreateDirectory(CurrentDirectory);
        }
        return true;
    }

    //shorting string

    #endregion

12 个答案:

答案 0 :(得分:51)

由于错误的原因很明显,这里有一些信息可以帮助您解决问题:

请参阅此MS article about Naming Files, Paths, and Namespaces

以下是链接中的引用:

  

最大路径长度限制在Windows API中(以下段落中讨论了一些例外),最大长度   对于路径是MAX_PATH,定义为260个字符。本地人   path按以下顺序构成:驱动器号,冒号,   反斜杠,名称由反斜杠分隔的组件和终止   空字符。例如,驱动器D上的最大路径是“D:\ some   256个字符的路径字符串&lt; NUL&gt;“其中”&lt; NUL&gt;“表示不可见的   终止当前系统代码页的空字符。 (该   字符&lt; &GT;这里使用的是视觉清晰度,不能成为其中的一部分   一个有效的路径字符串。)

以及一些解决方法(摘自评论):

有办法解决各种问题。下面列出的解决方案的基本思想始终相同:减少路径长度以获得path-length + name-length < MAX_PATH。你可以:

  • 分享子文件夹
  • 使用命令行通过SUBST
  • 分配驱动器号
  • 使用VB下的AddConnection为路径分配驱动器号

答案 1 :(得分:23)

有一个名为Zeta Long Paths的库,它提供了一个.NET API来处理长路径。

这是一篇很好的文章,涵盖.NET和PowerShell的这个问题:“.NET, PowerShell Path too Long Exception and a .NET PowerShell Robocopy Clone

答案 2 :(得分:8)

对我有用的解决方案是编辑注册表项以启用长路径行为,将该值设置为1。这是Windows 10的新选择启用功能

HKLM\SYSTEM\CurrentControlSet\Control\FileSystem LongPathsEnabled (Type: REG_DWORD)

我从@ james-hill发布的文章的命名部分获得了此解决方案。

https://docs.microsoft.com/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation

答案 3 :(得分:2)

在Windows 8.1上,使用。 NET 3.5,我遇到了类似的问题 虽然当我使用文件名(没有路径)实例化FileInfo对象时,我的文件名只有239个字符,但是发生了类型为System的异常。 IO.PathTooLongException

2014-01-22 11:10:35 DEBUG LogicalDOCOutlookAddIn.LogicalDOCAddIn - fileName.Length: 239 
2014-01-22 11:10:35 ERROR LogicalDOCOutlookAddIn.LogicalDOCAddIn - Exception in ImportEmail System.IO.PathTooLongException: Percorso e/o nome di file specificato troppo lungo. Il nome di file completo deve contenere meno di 260 caratteri, mentre il nome di directory deve contenere meno di 248 caratteri.
   in System.IO.Path.NormalizePathFast(String path, Boolean fullCheck)
   in System.IO.FileInfo..ctor(String fileName)
   in LogicalDOCOutlookAddIn.LogicalDOCAddIn.GetTempFilePath(String fileName) in C:\Users\alle\Documents\Visual Studio 2010\Projects\MyAddin1Outlook20072010\MyAddin1Outlook20072010\LogicalDOCAddIn.cs:riga 692
   in LogicalDOCOutlookAddIn.LogicalDOCAddIn.ImportEmail(_MailItem mailItem, OutlookConfigXML configXML, Int64 targetFolderID, String SID) in C:\Users\alle\Documents\Visual Studio 2010\Projects\MyAddin1Outlook20072010\MyAddin1Outlook20072010\LogicalDOCAddIn.cs:riga 857
   in LogicalDOCOutlookAddIn.LogicalDOCAddIn.ImportEmails(Explorers explorers, OutlookConfigXML configXML, Int64 targetFolderID, Boolean suppressResultMB) in C:\Users\alle\Documents\Visual Studio 2010\Projects\MyAddin1Outlook20072010\MyAddin1Outlook20072010\LogicalDOCAddIn.cs:riga 99

我解决了将文件名修剪为204个字符(包含扩展名)的问题。

答案 4 :(得分:2)

您可以使用较短的目录创建符号链接。 第一个打开命令行,例如Shift + RightClick在所需文件夹中的路径较短(您可能需要以管理员身份运行)。

然后键入相对或绝对路径:

mklink ShortPath\To\YourLinkedSolution C:\Path\To\Your\Solution /D

然后从较短的路径开始解决方案。这里的优点是:你不需要移动任何东西。

答案 5 :(得分:1)

如果由于路径较长而导致 bin 文件出现问题,则在Visual Studio 2015中,您可以转到违规项目的属性页并更改相对输出目录更短。

E.g。 bin \ debug \ 变为 C:\ _ bins \ MyProject \

答案 6 :(得分:1)

对我有用的是将我的项目从桌面(C:\ Users \ lachezar.l \ Desktop \ MyFolder)移到(C:\ 0 \ MyFolder),如您所见,它使用较短的路径并减小了它解决了问题。

答案 7 :(得分:0)

到目前为止还没有提及和更新,这里有一个非常完善的建立库,用于处理过长的路径。 AlphaFS是一个.NET库,它比标准System.IO类为.NET平台提供了更完整的Win32文件系统功能。标准.NET System.IO的最明显缺陷是缺乏对高级NTFS功能的支持,尤其是对扩展长度路径的支持(例如,文件/目录路径长于260个字符)。

答案 8 :(得分:0)

我能找到的最佳答案是在这里的评论之一。 将其添加到答案中,以便某人不会错过该评论,并且绝对应该尝试一下。它为我解决了这个问题。

我们需要使用命令提示符中的“ subst”命令将解决方案文件夹映射到驱动器- 例如,替换为z:

然后从该驱动器中打开解决方案(在本例中为z)。这样可以尽可能缩短路径,并可以解决冗长的文件名问题。

答案 9 :(得分:0)

根据我的经验,对于任何面向公众的Web应用程序,我不会推荐我的以下答案。

如果您需要它作为内部工具或测试用,我建议在您自己的计算机上共享它。

-Right click on the root path you need to access
-Choose Properties
-Click on Share button and add your chosen users who can access it

这将创建一个共享目录,例如\\ {PCName} \ {YourSharedRootDirectory} 这肯定比我希望的完整路径要少得多,对我来说,我可以从290个字符减少到30个字符。 :)

答案 10 :(得分:0)

这也可能是解决方案。有时将开发项目保持在太深的位置,这意味着项目目录可能包含太多目录,所以请不要创建太多目录以使其简单驱动器内的文件夹。例如,当我的项目保持这样的状态时,我也收到此错误-

D:\ Sharad \ LatestWorkings \ GenericSurveyApplication020120 \ GenericSurveyApplication \ GenericSurveyApplication

然后我只是将项目粘贴到内部

D:\ Sharad \ LatestWorkings \ GenericSurveyApplication

问题解决了。

答案 11 :(得分:-6)

您可以在以下位置缩小项目名称:

Solution Properties -> Application -> Assembly Name