web-dev-qa-db-ja.com

フルパスが指定されているかどうかを確認してください

指定されたパスがフルパスかどうかを確認する方法はありますか?今これをやっています:

if (template.Contains(":\\")) //full path already given
{
}
else //calculate the path from local Assembly
{
}

しかし、これをチェックするためのよりエレガントな方法が必要ですか?

94
hs2d

System.IO.Path.IsPathRootedを使用してみてください?また、絶対パスに対してtrueを返します。

System.IO.Path.IsPathRooted(@"c:\foo"); // true
System.IO.Path.IsPathRooted(@"\foo"); // true
System.IO.Path.IsPathRooted("foo"); // false

System.IO.Path.IsPathRooted(@"c:1\foo"); // surprisingly also true
System.IO.Path.GetFullPath(@"c:1\foo");// returns "[current working directory]\1\foo"
128
detaylor
_Path.IsPathRooted(path)
&& !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)
_

上記の条件:

  • ファイルシステムの権限は必要ありません
  • falseの形式が無効なほとんどの場合(例外をスローするのではなく)pathを返します
  • trueにボリュームが含まれる場合にのみpathを返します

したがって、OPが提示したシナリオのようなシナリオでは、前の回答の条件よりも適切な場合があります。上記の条件とは異なり:

  • path == System.IO.Path.GetFullPath(path)は、これらのシナリオでfalseを返すのではなく、例外をスローします:
    • 呼び出し元に必要な権限がありません
    • システムは絶対パスを取得できませんでした
    • パスに、ボリューム識別子の一部ではないコロン( ":")が含まれています
    • 指定されたパス、ファイル名、またはその両方がシステム定義の最大長を超えています
  • trueが単一のディレクトリ区切り文字で始まる場合、System.IO.Path.IsPathRooted(path)pathを返します。

最後に、上記の条件をラップし、残りの例外を除外するメソッドを次に示します。

_public static bool IsFullPath(string path) {
    return !String.IsNullOrWhiteSpace(path)
        && path.IndexOfAny(System.IO.Path.GetInvalidPathChars().ToArray()) == -1
        && Path.IsPathRooted(path)
        && !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal);
}
_

編集:EM0は良いコメントをし、 代替回答 _C:_や_C:dir_のようなパスの奇妙なケースに対処しました。そのようなパスをどのように処理するかを決定するには、MSDNの詳細をご覧ください->Windowsデスクトップアプリケーション->Develop->Desktop technology->データアクセスとストレージ->ローカルファイルシステム->ファイル管理->ファイル管理について->作成、ファイルの削除とメンテナンス->ファイル、パス、ネームスペースの命名-> 完全に修飾パスと相対パス

ファイルを操作するWindows API関数の場合、多くの場合、ファイル名は現在のディレクトリに関連する場合がありますが、一部のAPIは完全修飾パスを必要とします。ファイル名は、次のいずれかで始まらない場合、現在のディレクトリに相対的です。

  • 常に2つのバックスラッシュ文字( "\")で始まる任意の形式のUNC名。詳細については、次のセクションを参照してください。
  • 「C:\」または「d:\」などのバックスラッシュ付きのディスク指定子。
  • 単一のバックスラッシュ。たとえば、「\ directory」または「\ file.txt」。これは絶対パスとも呼ばれます。

ファイル名がディスク指定子のみで始まり、コロンの後のバックスラッシュではない場合、指定された文字のドライブ上の現在のディレクトリへの相対パスとして解釈されます。現在のディレクトリは、そのディスクでの最新の「ディレクトリの変更」操作中に設定された内容に応じて、ルートディレクトリである場合とそうでない場合があることに注意してください。この形式の例は次のとおりです。

  • 「C:tmp.txt」は、ドライブCの現在のディレクトリにある「tmp.txt」という名前のファイルを指します。
  • 「C:tempdir\tmp.txt」は、ドライブCの現在のディレクトリのサブディレクトリにあるファイルを指します。

[...]

26
weir

試してみる

System.IO.Path.IsPathRooted(template)

UNCパスとローカルパスの両方で機能します。

例えば。

Path.IsPathRooted(@"\\MyServer\MyShare\MyDirectory")  // returns true
Path.IsPathRooted(@"C:\\MyDirectory")  // returns true
15
Joe

古い質問ですが、もう1つ当てはまる答えです。ボリュームがローカルパスに含まれていることを確認する必要がある場合は、次のようにSystem.IO.Path.GetFullPath()を使用できます。

if (template == System.IO.Path.GetFullPath(template))
{
    ; //template is full path including volume or full UNC path
}
else
{
    if (useCurrentPathAndVolume)
        template = System.IO.Path.GetFullPath(template);
    else
        template = Assembly.GetExecutingAssembly().Location
}
12
GreggD

weirの答えに基づいて:これは無効なパスに対してスローされませんが、「C:」、「C:dirname」、「\ path」などのパスに対してfalseも返します。

public static bool IsFullPath(string path)
{
    if (string.IsNullOrWhiteSpace(path) || path.IndexOfAny(Path.GetInvalidPathChars()) != -1 || !Path.IsPathRooted(path))
        return false;

    string pathRoot = Path.GetPathRoot(path);
    if (pathRoot.Length <= 2 && pathRoot != "/") // Accepts X:\ and \\UNC\PATH, rejects empty string, \ and X:, but accepts / to support Linux
        return false;

    if (pathRoot[0] != '\\' || pathRoot[1] != '\\')
        return true; // Rooted and not a UNC path

    return pathRoot.Trim('\\').IndexOf('\\') != -1; // A UNC server name without a share name (e.g "\\NAME" or "\\NAME\") is invalid
}

これは、WindowsとLinuxでは異なる結果を返すことに注意してください。 「/ path」はLinuxでは絶対ですが、Windowsでは絶対ではありません。

単体テスト:

[Test]
public void IsFullPath()
{
    bool isWindows = Environment.OSVersion.Platform.ToString().StartsWith("Win"); // .NET Framework
    // bool isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows); // .NET Core

    // These are full paths on Windows, but not on Linux
    TryIsFullPath(@"C:\dir\file.ext", isWindows);
    TryIsFullPath(@"C:\dir\", isWindows);
    TryIsFullPath(@"C:\dir", isWindows);
    TryIsFullPath(@"C:\", isWindows);
    TryIsFullPath(@"\\unc\share\dir\file.ext", isWindows);
    TryIsFullPath(@"\\unc\share", isWindows);

    // These are full paths on Linux, but not on Windows
    TryIsFullPath(@"/some/file", !isWindows);
    TryIsFullPath(@"/dir", !isWindows);
    TryIsFullPath(@"/", !isWindows);

    // Not full paths on either Windows or Linux
    TryIsFullPath(@"file.ext", false);
    TryIsFullPath(@"dir\file.ext", false);
    TryIsFullPath(@"\dir\file.ext", false);
    TryIsFullPath(@"C:", false);
    TryIsFullPath(@"C:dir\file.ext", false);
    TryIsFullPath(@"\dir", false); // An "absolute", but not "full" path

    // Invalid on both Windows and Linux
    TryIsFullPath(null, false, false);
    TryIsFullPath("", false, false);
    TryIsFullPath("   ", false, false);
    TryIsFullPath(@"C:\inval|d", false, false);
    TryIsFullPath(@"\\is_this_a_dir_or_a_hostname", false, false);
    TryIsFullPath(@"\\is_this_a_dir_or_a_hostname\", false, !isWindows);
    TryIsFullPath(@"\\is_this_a_dir_or_a_hostname\\", false, !isWindows);
}

private static void TryIsFullPath(string path, bool expectedIsFull, bool expectedIsValid = true)
{
    Assert.AreEqual(expectedIsFull, PathUtils.IsFullPath(path), "IsFullPath('" + path + "')");

    if (expectedIsFull)
    {
        Assert.AreEqual(path, Path.GetFullPath(path));
    }
    else if (expectedIsValid)
    {
        Assert.AreNotEqual(path, Path.GetFullPath(path));
    }
    else
    {
        Assert.That(() => Path.GetFullPath(path), Throws.Exception);
    }
}
9
EM0

パスが 完全修飾(MSDN) かどうかを確認するには:

public static bool IsPathFullyQualified(string path)
{
    var root = Path.GetPathRoot(path);
    return root.StartsWith(@"\\") || root.EndsWith(@"\");
}

これは、すでに提案されているものよりも少し単純であり、C:fooなどのドライブ相対パスに対してはfalseを返します。そのロジックは、MSDNの「完全修飾」の定義に直接基づいており、誤動作する例は見当たりません。


ただし、興味深いことに、.NET Core 2.1には、内部メソッド Path.IsPathFullyQualified (2018-04-17現在のリンク位置が正確)を使用する新しいメソッドPathInternal.IsPartiallyQualifiedがあるようです。

このポストの子孫とより良い自己抑制のために、参照のための後者の実装があります:

internal static bool IsPartiallyQualified(ReadOnlySpan<char> path)
{
    if (path.Length < 2)
    {
        // It isn't fixed, it must be relative.  There is no way to specify a fixed
        // path with one character (or less).
        return true;
    }

    if (IsDirectorySeparator(path[0]))
    {
        // There is no valid way to specify a relative path with two initial slashes or
        // \? as ? isn't valid for drive relative paths and \??\ is equivalent to \\?\
        return !(path[1] == '?' || IsDirectorySeparator(path[1]));
    }

    // The only way to specify a fixed path that doesn't begin with two slashes
    // is the drive, colon, slash format- i.e. C:\
    return !((path.Length >= 3)
        && (path[1] == VolumeSeparatorChar)
        && IsDirectorySeparator(path[2])
        // To match old behavior we'll check the drive character for validity as the path is technically
        // not qualified if you don't have a valid drive. "=:\" is the "=" file's default data stream.
        && IsValidDriveChar(path[0]));
}
4
William

これは私が使用するソリューションです

public static bool IsFullPath(string path)
{
    try
    {
        return Path.GetFullPath(path) == path;
    }
    catch
    {
        return false;
    }
}

次のように機能します。

IsFullPath(@"c:\foo"); // true
IsFullPath(@"C:\foo"); // true
IsFullPath(@"c:\foo\"); // true
IsFullPath(@"c:/foo"); // false
IsFullPath(@"\foo"); // false
IsFullPath(@"foo"); // false
IsFullPath(@"c:1\foo\"); // false

フルパス(例からはルートからの相対的でないことを意味しますが)の意味がわかりません Path クラスを使用して、物理ファイルシステムパスの操作を支援できます。これにより、ほとんどの場合に対応できます。

0
Grant Thomas