文字列が有効なWindowsディレクトリ(フォルダ)パスであるかどうかを確認します


84

ユーザーが入力した文字列がフォルダへのパスを表すのに有効かどうかを判断しようとしています。有効とは、適切にフォーマットされていることを意味します。

私のアプリケーションでは、フォルダーはインストール先を表します。フォルダパス有効であれば、フォルダが存在するかどうかを確認し、存在しない場合は作成します。

現在使用していIO.Directory.Exists( String path )ます。ユーザーが文字列を適切にフォーマットしない場合を除いて、これは正常に機能することがわかりました。その場合、このメソッドはfalseを返します。これは、フォルダーが存在しないことを示します。しかし、後でフォルダを作成できなくなるため、これは問題です。

グーグルから、正規表現を使用して形式が適切かどうかを確認するという提案を見つけました。私は正規表現の経験がなく、それが実行可能なアプローチであるかどうか疑問に思っています。これが私が見つけたものです:

Regex r = new Regex( @"^(([a-zA-Z]\:)|(\\))(\\{1}|((\\{1})[^\\]([^/:*?<>""|]*))+)$" );
return r.IsMatch( path );

と組み合わせた正規表現テストは、パスが有効かどうか、およびパスが存在するかどうかを確認するのに十分な方法をDirectory.Exists()教えてくれますか?これはOSやその他の要因によって異なることはわかっていますが、このプログラムはWindowsユーザーのみを対象としています


1
Directory.Existsがfalseを返した後にディレクトリが作成されない場合、それはユーザーが間違った入力を提供したことを示すかなり良い兆候ではありませんか?
ロバートハーベイ



2
@Robert私はその質問を見ました、そしてそれは一般的な規則以外の特定の答えを提供しませんでした。2番目に高い回答は、フォーマットではなく、無効な文字のみを対象としていました。また、Directory.Existsメソッドはfalseを返す可能性がありますが、その場でフォルダーを作成するオプションが必要なため、それだけでは実行できません。
Pudpuduk 2010年

@Robertリンクした2番目のトピックについて、1つの単語を入力しても、その質問への回答に記載されている検証に合格します。
Pudpuduk 2010年

回答:


116

呼び出すPath.GetFullPath; パスが無効な場合は例外がスローされます。

相対パス(などWord)を禁止するには、を呼び出します Path.IsPathRooted


もっと簡単なものがあることを私は知っていました!そして、おかげで、私はパスが相対的な問題であるとは考えていませんでした。
Pudpuduk 2010年

2
SLaksに感謝します。私は多くの重複を見て、(複数回)多くのGoogle検索を行いましたが、この特定の質問に対する良い答えを見たのはこれが初めてです。
ロバートハーベイ

5
Path.GetFullPath( "con.txt")は有効なファイル名です。
クリストファー

8
@Slaksこれは古すぎてコメントを残すことができませんが、-1の投票をしたので、ここにコメントを残したいと思います。Path.GetFullPath()は正常に機能しているようですが、パスが「Z:\\\\\\\\ Hi \\\\\\ There」の場合、有効な絶対パスではなく、Path.GetFullPathです。 (...)結果を出します:Z:\ Hi \ Thereそして例外は発生しません。GetFullPath()によって返される文字列と、次のように元の文字列を比較して、少し変更する必要がありました。privatebool IsPathValid(string path){try {string fullPath = Path.GetFullPath(path); fullPath == pathを返します。} catch {return false;}}
キングキング

4
@KingKing unix.stackexchange.comのこのLinuxの回答から:「複数のスラッシュが許可されており、単一のスラッシュと同等です。」私はWindowsでも同じことを観察しました(ただし、UNCパスの先頭のスラッシュは異なる方法で処理される場合があります)。これを証明するために、コマンドプロンプトで次のことを試してくださいcd C:\\\\\\\Windows\\\\\\\System32。Windowsの場合、この動作を文書化した信頼できるソースを見つけることができませんが、もちろん、そのポインターを歓迎します。
DavidRR 2016

20

私は実際にSLaksに同意しません。その解決策は私にはうまくいきませんでした。期待どおりに例外が発生しませんでした。しかし、このコードは私のために働きました:

if(System.IO.Directory.Exists(path))
{
    ...
}

62
有効なパスは必ずしも存在するディレクトリではありません...これはまさにここで尋ねられる問題です
Benlitz 2013

1
質問は、存在しない可能性のあるパスであるパス文字列の検証に関連していました。
mubashar 2013

この方法は正しいと思います。例外は予期されるべきではありません。このメソッドは、指定されたパスの誤った文字もチェックします。
ユージーンマクシモフ2016

Directory.Existsには有効なパスが必要なため、「パス」が実際のパスではないことが判明した場合、この条件自体が例外をスローします。
M. Fawad Surosh 2017年

完全に間違った答え!どうやって32の賛成票を受け取ったのだろうか(今のところ)。彼らが直面している問題のために間違った場所を見ていた人々によるものであるに違いありません、そして彼らはこれにつまずきました。
Sнаđошƒаӽ

13

Path.GetFullPathは、以下の例外のみを提供します

ArgumentExceptionパスが長さゼロの文字列であるか、空白のみが含まれているか、GetInvalidPathCharsで定義されている1つ以上の無効な文字が含まれています。-または-システムは絶対パスを取得できませんでした。

SecurityException呼び出し元に必要な権限がありません。

ArgumentNullExceptionパスがnullです。

NotSupportedExceptionパスに、ボリューム識別子( "c:\"など)の一部ではないコロン( ":")が含まれています。

PathTooLongException指定されたパス、ファイル名、またはその両方が、システム定義の最大長を超えています。たとえば、Windowsベースのプラットフォームでは、パスは248文字未満である必要があり、ファイル名は260文字未満である必要があります。

別の方法は、以下を使用することです。

/// <summary>
/// Validate the Path. If path is relative append the path to the project directory by default.
/// </summary>
/// <param name="path">Path to validate</param>
/// <param name="RelativePath">Relative path</param>
/// <param name="Extension">If want to check for File Path</param>
/// <returns></returns>
private static bool ValidateDllPath(ref string path, string RelativePath = "", string Extension = "")
{
    // Check if it contains any Invalid Characters.
    if (path.IndexOfAny(Path.GetInvalidPathChars()) == -1)
    {
        try
        {
            // If path is relative take %IGXLROOT% as the base directory
            if (!Path.IsPathRooted(path))
            {
                if (string.IsNullOrEmpty(RelativePath))
                {
                    // Exceptions handled by Path.GetFullPath
                    // ArgumentException path is a zero-length string, contains only white space, or contains one or more of the invalid characters defined in GetInvalidPathChars. -or- The system could not retrieve the absolute path.
                    // 
                    // SecurityException The caller does not have the required permissions.
                    // 
                    // ArgumentNullException path is null.
                    // 
                    // NotSupportedException path contains a colon (":") that is not part of a volume identifier (for example, "c:\"). 
                    // PathTooLongException The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.

                    // RelativePath is not passed so we would take the project path 
                    path = Path.GetFullPath(RelativePath);

                }
                else
                {
                    // Make sure the path is relative to the RelativePath and not our project directory
                    path = Path.Combine(RelativePath, path);
                }
            }

            // Exceptions from FileInfo Constructor:
            //   System.ArgumentNullException:
            //     fileName is null.
            //
            //   System.Security.SecurityException:
            //     The caller does not have the required permission.
            //
            //   System.ArgumentException:
            //     The file name is empty, contains only white spaces, or contains invalid characters.
            //
            //   System.IO.PathTooLongException:
            //     The specified path, file name, or both exceed the system-defined maximum
            //     length. For example, on Windows-based platforms, paths must be less than
            //     248 characters, and file names must be less than 260 characters.
            //
            //   System.NotSupportedException:
            //     fileName contains a colon (:) in the middle of the string.
            FileInfo fileInfo = new FileInfo(path);

            // Exceptions using FileInfo.Length:
            //   System.IO.IOException:
            //     System.IO.FileSystemInfo.Refresh() cannot update the state of the file or
            //     directory.
            //
            //   System.IO.FileNotFoundException:
            //     The file does not exist.-or- The Length property is called for a directory.
            bool throwEx = fileInfo.Length == -1;

            // Exceptions using FileInfo.IsReadOnly:
            //   System.UnauthorizedAccessException:
            //     Access to fileName is denied.
            //     The file described by the current System.IO.FileInfo object is read-only.-or-
            //     This operation is not supported on the current platform.-or- The caller does
            //     not have the required permission.
            throwEx = fileInfo.IsReadOnly;

            if (!string.IsNullOrEmpty(Extension))
            {
                // Validate the Extension of the file.
                if (Path.GetExtension(path).Equals(Extension, StringComparison.InvariantCultureIgnoreCase))
                {
                    // Trim the Library Path
                    path = path.Trim();
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return true;

            }
        }
        catch (ArgumentNullException)
        {
            //   System.ArgumentNullException:
            //     fileName is null.
        }
        catch (System.Security.SecurityException)
        {
            //   System.Security.SecurityException:
            //     The caller does not have the required permission.
        }
        catch (ArgumentException)
        {
            //   System.ArgumentException:
            //     The file name is empty, contains only white spaces, or contains invalid characters.
        }
        catch (UnauthorizedAccessException)
        {
            //   System.UnauthorizedAccessException:
            //     Access to fileName is denied.
        }
        catch (PathTooLongException)
        {
            //   System.IO.PathTooLongException:
            //     The specified path, file name, or both exceed the system-defined maximum
            //     length. For example, on Windows-based platforms, paths must be less than
            //     248 characters, and file names must be less than 260 characters.
        }
        catch (NotSupportedException)
        {
            //   System.NotSupportedException:
            //     fileName contains a colon (:) in the middle of the string.
        }
        catch (FileNotFoundException)
        {
            // System.FileNotFoundException
            //  The exception that is thrown when an attempt to access a file that does not
            //  exist on disk fails.
        }
        catch (IOException)
        {
            //   System.IO.IOException:
            //     An I/O error occurred while opening the file.
        }
        catch (Exception)
        {
            // Unknown Exception. Might be due to wrong case or nulll checks.
        }
    }
    else
    {
        // Path contains invalid characters
    }
    return false;
}

9

これは、@ SLaksの回答で推奨されているPath.GetFullPathの使用を活用するソリューションです。

ここに含まれているコードでIsValidPath(string path)は、呼び出し元が例外処理について心配する必要がないように設計されていることに注意してください。

またTryGetFullPath(...)絶対パスを安全に取得しようとする場合、それが呼び出すメソッド自体にもメリットがあることがわかります

/// <summary>
/// Gets a value that indicates whether <paramref name="path"/>
/// is a valid path.
/// </summary>
/// <returns>Returns <c>true</c> if <paramref name="path"/> is a
/// valid path; <c>false</c> otherwise. Also returns <c>false</c> if
/// the caller does not have the required permissions to access
/// <paramref name="path"/>.
/// </returns>
/// <seealso cref="Path.GetFullPath"/>
/// <seealso cref="TryGetFullPath"/>
public static bool IsValidPath(string path)
{
    string result;
    return TryGetFullPath(path, out result);
}

/// <summary>
/// Returns the absolute path for the specified path string. A return
/// value indicates whether the conversion succeeded.
/// </summary>
/// <param name="path">The file or directory for which to obtain absolute
/// path information.
/// </param>
/// <param name="result">When this method returns, contains the absolute
/// path representation of <paramref name="path"/>, if the conversion
/// succeeded, or <see cref="String.Empty"/> if the conversion failed.
/// The conversion fails if <paramref name="path"/> is null or
/// <see cref="String.Empty"/>, or is not of the correct format. This
/// parameter is passed uninitialized; any value originally supplied
/// in <paramref name="result"/> will be overwritten.
/// </param>
/// <returns><c>true</c> if <paramref name="path"/> was converted
/// to an absolute path successfully; otherwise, false.
/// </returns>
/// <seealso cref="Path.GetFullPath"/>
/// <seealso cref="IsValidPath"/>
public static bool TryGetFullPath(string path, out string result)
{
    result = String.Empty;
    if (String.IsNullOrWhiteSpace(path)) { return false; }
    bool status = false;

    try
    {
        result = Path.GetFullPath(path);
        status = true;
    }
    catch (ArgumentException) { }
    catch (SecurityException) { }
    catch (NotSupportedException) { }
    catch (PathTooLongException) { }

    return status;
}

6

このコードを使用する

string DirectoryName = "Sample Name For Directory Or File";
Path.GetInvalidFileNameChars()
  .Where(x => DirectoryName.Contains(x))
  .Count() > 0 || DirectoryName == "con"

4
同じことを達成する少し短いコード: Path.GetInvalidFileNameChars().Any(DirectoryName.Contains) || DirectoryName == "con"
bsegraves 2012年

2
@nawfal確かに。MSDNのファイル、パス、および名前空間の命名から:
DavidRR 2016

この「ブラックリストアプローチ」は、すべてのWindowsシステムで機能するわけではありません。たとえば、絵文字が表示される場合:en.wikipedia.org/wiki/Miscellaneous_Symbols_and_Pictographs
1

4
    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;
    }

3

私はこのコードに問題はありませんでした:

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

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

        if (exactPath)
        {
            string root = Path.GetPathRoot(path);
            isValid = string.IsNullOrEmpty(root.Trim(new char[] { '\\', '/' })) == false;
        }
        else
        {
            isValid = Path.IsPathRooted(path);
        }
    }
    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");
IsValidPath("abc");
IsValidPath("abc", false);

そして、これらは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", false);

0

よりシンプルなOSに依存しないソリューション。

public static class PathHelper
{
    public static void ValidatePath(string path)
    {
        if (!Directory.Exists(path))
            Directory.CreateDirectory(path).Delete();
    }
}

使用法:

try
{
    PathHelper.ValidatePath(path);
}
catch(Exception e)
{
    // handle exception
}

Directory.CreateDirectory() 次のすべての状況で自動的にスローされます。

System.IO.IOException:
パスで指定されたディレクトリはファイルです。-または-ネットワーク名が不明です。

System.UnauthorizedAccessException:
呼び出し元に必要な権限がありません。

System.ArgumentException:
パスが長さゼロの文字列であるか、空白のみが含まれているか、1つ以上の無効な文字が含まれています。System.IO.Path.GetInvalidPathCharsメソッドを使用して、無効な文字を照会できます。-または-パスの前にコロン文字(:)のみが付いているか、含まれています。

System.ArgumentNullException:
パスがnullです。

System.IO.PathTooLongException:
指定されたパス、ファイル名、またはその両方が、システム定義の最大長を超えています。

System.IO.DirectoryNotFoundException:
指定されたパスが無効です(たとえば、マップされていないドライブ上にあります)。

System.NotSupportedException:
パスにドライブラベル( "C:")の一部ではないコロン文字(:)が含まれています。

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