2011-06-05 60 views
3

由於.NET不包含用於製作相對路徑的API,因此我使用了Uri的MakeRelativeUri方法。這有效,但我遇到過幾起案件,因爲Uri沒有逃脫。所以,我已經修補了,太多:這種製作相對路徑的方法是否有效?

public static string MakeRelativePath(string basePath, string tgtPath) { 
    return 
     Uri.UnescapeDataString(
      new Uri(basePath, UriKind.Absolute) 
       .MakeRelativeUri(new Uri(tgtPath, UriKind.Absolute)) 
      .ToString() 
     ).Replace('/', Path.DirectorySeparatorChar); 
} 

此版本似乎工作,但它讓我感覺有點quesy:不存在任何有效的本地文件系統路徑,這沒來由的轉義可能會損壞?

相關:How to get relative path from absolute path 的答案,這個問題不解決的特殊字符和逃避所有的問題,因此不回答這個問題。

+0

的[如何從絕對路徑相對路徑(http://stackoverflow.com/questions/275689/how-to-get-relative-path-from-absolute-path) – 2011-06-05 16:00:18

+0

可能重複@ Eamon這裏有一些很好的答案:http://stackoverflow.com/questions/275689/how-to-get-relative-path-from-absolute-path如果是我,我會去解決方案,P /調用到'PathRelativePathTo()' – 2011-06-05 16:00:43

+0

是的,我看到一個也在使用Uri的答案,儘管沒有逃脫,即borked。 P /調用;好吧,這是緩慢的和依賴於平臺的,這意味着你可能遇到x86/x64問題,非滿意信任問題,當然像silverlight/XNA這樣的東西不一定支持它。它會工作,但這不是我的第一選擇。 – 2011-06-05 18:55:30

回答

4

您可以使用System.UriPathDifference方法使用的底層算法代替轉義,反轉和替換。在這裏,通過Reflector恢復並修改以獲得更好的可讀性。它也被修改爲使用DOS樣式路徑的反斜槓而不是URI的正斜槓,並且比較總是不區分大小寫。

static string PathDifference(string path1, string path2) 
{ 
    int c = 0; //index up to which the paths are the same 
    int d = -1; //index of trailing slash for the portion where the paths are the same 

    while (c < path1.Length && c < path2.Length) 
    { 
     if (char.ToLowerInvariant(path1[c]) != char.ToLowerInvariant(path2[c])) 
     { 
      break; 
     } 

     if (path1[c] == '\\') 
     { 
      d = c; 
     } 

     c++; 
    } 

    if (c == 0) 
    { 
     return path2; 
    } 

    if (c == path1.Length && c == path2.Length) 
    { 
     return string.Empty; 
    } 


    System.Text.StringBuilder builder = new System.Text.StringBuilder(); 

    while (c < path1.Length) 
    { 
     if (path1[c] == '\\') 
     { 
      builder.Append(@"..\"); 
     } 
     c++; 
    } 

    if (builder.Length == 0 && path2.Length - 1 == d) 
    { 
     return @".\"; 
    } 

    return builder.ToString() + path2.Substring(d + 1); 
} 

對輸入的期望似乎是,如果任一路徑代表一個目錄,它必須有一個尾部反斜槓。顯然,路徑也必須是非空的。

以下是一些示例輸入和輸出...看看它是否符合您的需求。

Path1     Path2    Output 
C:\test\path1\path2\ C:\test\   ..\..\ 
C:\test\path1\file  C:\test\   ..\ 
C:\test\path1\path2\ C:\     ..\..\..\ 
C:\test\path1\path2\ D:\     D:\ 
C:\test\path1\path2\ C:\test\path1\pathA ..\pathA 
C:\test\    C:\test\  
C:\test\    C:\test\file  file 
C:\test\file   C:\test\   .\ 
C:\test\path #1!\path2\ C:\test\   ..\..\ 
+0

是的,後面的反斜槓事情是相當固有的,如果你考慮一下 - 算法實際上並沒有訪問文件系統,對吧? – 2011-06-05 18:45:37

+0

順便說一句,謝謝你的努力,這當然是一個有趣的方法! – 2011-06-05 18:48:51

相關問題