2

相対URI()からLocalPathを計算する標準的な方法はないようです。たとえば、ファイルマスク(* .ext)と組み合わせて使用​​します。問題は、の代わりに、に似たものを生成することです。this property is valid only for absolute URIsPath.CombineMakeRelativeUrimy%20folder/my folder\

これが私が見つけた回避策です:

Module Module1
  Sub Main()
    Dim path1 As String = "C:\my folder\"
    Dim path2 As String = "C:\"
    MsgBox(GetPathDiff(path1, path2)) 'outputs "my folder\" (without quotes)
  End Sub

  Private Function GetPathDiff(path1 As String, path2 As String) As String
    Dim uri1 As New Uri(path1)
    Dim uri2 As New Uri(path2)
    Dim uri3 As Uri = uri2.MakeRelativeUri(uri1)
    Return Uri.UnescapeDataString(uri3.OriginalString).Replace("/", "\")
  End Function
End Module

私はそれがかなり不器用な方法だと思います、そして私がまだつまずいたいくつかの隠された石があるかもしれません、すなわちこの方法は異なるユースケースに対して100%安定していません。

それを行うためのより良い方法はありますか?

4

2 に答える 2

2

(注:嘆きほどの答えではありませんが、これが参考になることを願っています。)

ここで実行しようとしているのが2つのファイルシステムパス間の相対パスを取得することである場合は、filesytemAPIを使用するのが最善です。

当初、あるルートを基準にしたパスの計算に関する質問-Path.Combineの逆は、あなたと同じことを目指しているように見えました。この段落にEDITを適用する前に、それを確認することを提案しました。しかし、よく調べてみると、私が書いた時点での解決策はそれほど素晴らしいものではないことがわかりました。

ここで私が心配してUriいるのは、URIパスのルールを中心に設計されていることです。これは、ファイルシステムパスのルールと必ずしも同じではありません。たとえば、URI仕様では、「。」のパスセグメントが示されています。は「相対パス参照の先頭で使用することを目的としています」が、ファイルシステムパスでは、パスの途中に配置することは完全に合法です(少し奇妙な場合)。たとえばc:\.\a\.\b\.\c、合法であり、と同じ意味c:\a\b\cです。

ファイルシステムの正規化は間違いやすいことで有名なので、これよりも微妙な問題がある可能性があります。

したがって、理論的には、ファイルシステム固有のAPIは、ファイルシステムで機能する結果を生成することを期待して、URIを処理するように設計されたコードを使用するよりも優れています。実際には、.NETは相対パスを計算するためのファイルシステム対応APIを提供していないようです。驚くべきことに、この正確な目的のためのWin32 APIは、PathRelativePathToその「。」を取得します。間違った問題...

于 2013-02-07T21:36:58.650 に答える
1

[編集]さて、少し熟考した後、私別の方法を思いつきましたが、それはすべての人にとって口に合うとは限りません。

void Main()
{
    var path1 = @"C:\Program Files\Internet Explorer\";
    var path2 = @"C:\temp\";
    var sb = new StringBuilder(1000);
    PathRelativePathTo(sb, path1, 0, path2, 0);
    sb.ToString().Dump();
}

/*
BOOL PathRelativePathTo(
  _Out_  LPTSTR pszPath,
  _In_   LPCTSTR pszFrom,
  _In_   DWORD dwAttrFrom,
  _In_   LPCTSTR pszTo,
  _In_   DWORD dwAttrTo
);
*/
[DllImport("Shlwapi.dll")]
[return:MarshalAs(UnmanagedType.Bool)]
public static extern bool PathRelativePathTo(
    [Out] StringBuilder result,
    [In] string pathFrom,
    [In] int dwAttrFrom,
    [In] string pathTo,
    [In] int dwAttrTo);

ああ、ちょうどアイデアがありました-これはあなたに(多かれ少なかれ)あなたが必要とするものを手に入れますか?

public string PathDiff(string path1, string path2)
{
    var replace1 = path1.Replace(path2, string.Empty);
    var replace2 = path2.Replace(path1, string.Empty);
    return Path.IsPathRooted(replace1) ? replace2 : replace1;
}

またはおそらくより良い:

public string PathDiff(string path1, string path2)
{
    return path1.Length > path2.Length ? 
        path1.Replace(path2, string.Empty) : 
        path2.Replace(path1, string.Empty);
}

(編集:derp、送信を早すぎます):

残念ながら、組み込みの相対パスヘルパーはありませんが、基本的には、次のように、持っているものでそれを手に入れることができます。

var path1 = @"C:\dev\src\release\Frontend\";
var path2 = @"C:\dev\src\";

var path1Uri = new Uri(path1);
var path2Uri = new Uri(path2);

var from1to2 = path1Uri.MakeRelativeUri(path2Uri).OriginalString;
var from2to1 = path2Uri.MakeRelativeUri(path1Uri).OriginalString;

Console.WriteLine("To go from {0} to {1}, you need to {2}", path1, path2, from1to2);
Console.WriteLine("To go from {0} to {1}, you need to {2}", path2, path1, from2to1);

出力:

To go from C:\dev\src\release\Frontend\ to C:\dev\src\, you need to ../../
To go from C:\dev\src\ to C:\dev\src\release\Frontend\, you need to release/Frontend/

ここで、スラッシュの違い「\」と「/」については、最終結果をでラップPath.GetFullPathすると、違いが自動解決されます。

Console.WriteLine(Path.GetFullPath(Path.Combine(path1, from1to2)));
Console.WriteLine(Path.GetFullPath(Path.Combine(path2, from2to1)));

出力:

C:\dev\src\
C:\dev\src\release\Frontend\
于 2013-02-07T18:34:26.740 に答える