パスが有効かどうかを確認する


110

私はただ疑問に思っています。与えられたパスが有効かどうかを検証する方法を探しています。 (注:ファイルが存在するかどうかを確認したくない!パスの有効性を証明したいだけなので、その場所にファイルが存在する可能性がある場合)

問題は、.Net APIで何も見つからないことです。Windowsがサポートする多くのフォーマットと場所のため、私はむしろMSネイティブの何かを使用したいと思います。

関数は以下に対してチェックできるはずなので、

  • 相対パス(./)
  • 絶対パス(c:\ tmp)
  • UNCパス(\ some-pc \ c $)
  • フルパス1024文字のようなNTFSの制限-パスを超えて間違えていないと、多くのWindowsの内部機能でファイルにアクセスできなくなります。Explorerで名前を変更しても機能する
  • ボリュームGUIDパス: "\?\ Volume {GUID} \ somefile.foo

誰かがこのような機能を持っていますか?


回答:


58

試してくださいUri.IsWellFormedUriString()

  • 文字列は正しくエスケープされていません。

    http://www.example.com/path???/file name
  • 文字列は、暗黙のファイルUriを表す絶対Uriです。

    c:\\directory\filename
  • 文字列は、パスの前にスラッシュが欠落している絶対URIです。

    file://c:/directory/filename
  • 文字列には、スラッシュとして扱われる場合でも、エスケープされていないバックスラッシュが含まれています。

    http:\\host/path/file
  • 文字列は階層的な絶対URIを表し、「://」は含まれません。

    www.example.com/path/file
  • Uri.Schemeのパーサーは、元の文字列が整形式ではなかったことを示しています。

    The example depends on the scheme of the URI.

9
これはに対してfalseを返します@"foo\bar\baz"。これは完全に有効な相対パスです...
Thomas Levesque '18

5
トーマス:どのUriKindを指定しましたか?Absolute、Relative、またはAbsoluteOrRelativeを使用できます。
DanGøranLunde 2013

1
UriKindがRelativeまたはAbsoluteOrRelativeであっても、Thomasが述べたように相対パスでは機能しませんでした。私は代わりにPatkoの回答を使用することになりました。
JohnnyM 2014

1
IsWellFormedUriStringを使用すると、\\ computerName \ Dir Name With Spaces \ fileNameなどのパスが例外をスローすることがわかりました(最初の期待に反して)。スペースが正しくエンコードされていないためです。検証としてUri(string)コンストラクターを使用するだけでよいため、検証前に文字列を適切にエンコードする必要がないことがわかりました。
典型的な5 2014

3
完全に細かいファイルパスではfalseを返します。
エフゲニペトロフ


7
private bool IsValidPath(string path)
{
    Regex driveCheck = new Regex(@"^[a-zA-Z]:\\$");
    if (!driveCheck.IsMatch(path.Substring(0, 3))) return false;
    string strTheseAreInvalidFileNameChars = new string(Path.GetInvalidPathChars());
    strTheseAreInvalidFileNameChars += @":/?*" + "\"";
    Regex containsABadCharacter = new Regex("[" + Regex.Escape(strTheseAreInvalidFileNameChars) + "]");
    if (containsABadCharacter.IsMatch(path.Substring(3, path.Length - 3)))
        return false;

    DirectoryInfo dir = new DirectoryInfo(Path.GetFullPath(path));
    if (!dir.Exists)
        dir.Create();
    return true;
}

7

以下のコードで問題はありませんでした。(相対パスは「/」または「\」で始まる必要があります)。

private bool IsValidPath(string path, bool allowRelativePaths = false)
{
    bool isValid = true;

    try
    {
        string fullPath = Path.GetFullPath(path);

        if (allowRelativePaths)
        {
            isValid = Path.IsPathRooted(path);
        }
        else
        {
            string root = Path.GetPathRoot(path);
            isValid = string.IsNullOrEmpty(root.Trim(new char[] { '\\', '/' })) == false;
        }
    }
    catch(Exception ex)
    {
        isValid = false;
    }

    return isValid;
}

たとえば、これらはfalseを返します。

IsValidPath("C:/abc*d");
IsValidPath("C:/abc?d");
IsValidPath("C:/abc\"d");
IsValidPath("C:/abc<d");
IsValidPath("C:/abc>d");
IsValidPath("C:/abc|d");
IsValidPath("C:/abc:d");
IsValidPath("");
IsValidPath("./abc");
IsValidPath("./abc", true);
IsValidPath("/abc");
IsValidPath("abc");
IsValidPath("abc", true);

そして、これらはtrueを返します:

IsValidPath(@"C:\\abc");
IsValidPath(@"F:\FILES\");
IsValidPath(@"C:\\abc.docx\\defg.docx");
IsValidPath(@"C:/abc/defg");
IsValidPath(@"C:\\\//\/\\/\\\/abc/\/\/\/\///\\\//\defg");
IsValidPath(@"C:/abc/def~`!@#$%^&()_-+={[}];',.g");
IsValidPath(@"C:\\\\\abc////////defg");
IsValidPath(@"/abc", true);
IsValidPath(@"\abc", true);

3

あなたはこのコードを試すことができます:

try
{
  Path.GetDirectoryName(myPath);
}
catch
{
  // Path is not valid
}

それがすべてのケースをカバーするかどうかはわかりません...


2

私が来た最も近いのは、それを作成しようとし、それが成功するかどうかを確認することです。


2

ここにはたくさんの良い解決策がありますが、どれもパスが既存のドライブにルートされているかどうかを確認することはできません。

private bool IsValidPath(string path)
{
    // Check if the path is rooted in a driver
    if (path.Length < 3) return false;
    Regex driveCheck = new Regex(@"^[a-zA-Z]:\\$");
    if (!driveCheck.IsMatch(path.Substring(0, 3))) return false;

    // Check if such driver exists
    IEnumerable<string> allMachineDrivers = DriveInfo.GetDrives().Select(drive => drive.Name);
    if (!allMachineDrivers.Contains(path.Substring(0, 3))) return false;

    // Check if the rest of the path is valid
    string InvalidFileNameChars = new string(Path.GetInvalidPathChars());
    InvalidFileNameChars += @":/?*" + "\"";
    Regex containsABadCharacter = new Regex("[" + Regex.Escape(InvalidFileNameChars) + "]");
    if (containsABadCharacter.IsMatch(path.Substring(3, path.Length - 3)))
        return false;
    if (path[path.Length - 1] == '.') return false;

    return true;
}

このソリューションでは、相対パスは考慮されませ


1

から無効な文字を取得し、System.IO.Path.GetInvalidPathChars();文字列(ディレクトリパス)にそれらが含まれているかどうかを確認します。


3
これは完全に有効ではありません。「C:\ new.folder」は「C:\ newfolder」の間有効です。ではありません。「」パス/ファイル名の有効な文字ですが、URIの末尾にはありません。
claudekennilol 2013年

0

4
「[...]ファイルが存在するかどうかを確認したくない!」
Stefan

3
ディレクトリが存在するかどうかのテストは、ディレクトリが有効なパスではない(適切な権限が与えられた場合に存在する、または作成される可能性がある)ためではありません
Martijn

3
@Jason-ファイルはチェックせず、格納フォルダーのみをチェックします。
markpsmith

8
しかし、有効なディレクトリパスがまだ存在していない可能性があります。
Stefan

-2
private bool IsValidPath(string path)
{
    Regex driveCheck = new Regex(@"^[a-zA-Z]:\\$");

    if (string.IsNullOrWhiteSpace(path) || path.Length < 3)
    {
        return false;
    }

    if (!driveCheck.IsMatch(path.Substring(0, 3)))
    {
        return false;
    }

    var x1 = (path.Substring(3, path.Length - 3));
    string strTheseAreInvalidFileNameChars = new string(Path.GetInvalidPathChars());
    strTheseAreInvalidFileNameChars += @":?*";
    Regex containsABadCharacter = new Regex("[" + Regex.Escape(strTheseAreInvalidFileNameChars) + "]");

    if (containsABadCharacter.IsMatch(path.Substring(3, path.Length - 3)))
    {
        return false;
    }

    var driveLetterWithColonAndSlash = Path.GetPathRoot(path);

    if (!DriveInfo.GetDrives().Any(x => x.Name == driveLetterWithColonAndSlash))
    {
        return false;
    }

    return true;
}

1
x1の目的は何ですか?
JayJay 2017


-4

Path.IsPathRooted()をPath.GetInvalidFileNameChars()と組み合わせて使用​​して、パスが半分正常であることを確認できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.