문자열이 유효한 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를 반환 한 후 디렉터리를 생성하지 않으면 사용자가 잘못된 입력을 제공했음을 나타내는 좋은 표시가 아닙니까?
— Robert Harvey



2
@Robert 나는 그 질문을 보았고 일반적인 규칙 이외의 구체적인 대답을 제공하지 않았습니다. 두 번째로 높은 답변은 서식이 아니라 유효하지 않은 문자 만 다루었습니다. 또한 Directory.Exists 메서드는 false를 반환 할 수 있지만 그 자리에서 폴더를 만드는 옵션을 원하기 때문에 그냥 갈 수는 없습니다.
— Pudpuduk 2010-06-29

@Robert 링크 한 두 번째 주제에서 한 단어를 입력해도 해당 질문에 대한 답변에 제공된 유효성 검사를 통과합니다.
— Pudpuduk 2010-06-29

답변:


116

전화 Path.GetFullPath; 경로가 유효하지 않으면 예외가 발생합니다.

(예 : 상대 경로를 허용하려면 Word, 전화) Path.IsPathRooted.


더 간단한 것이 있다는 것을 알았습니다! 그리고 감사합니다. 나는 경로가 상대적인 문제에 대해 생각하지 않았습니다.
— Pudpuduk

2
감사합니다 SLaks. 나는 많은 중복을 보았고 많은 Google 검색을 (두 번 이상) 수행했지만이 특정 질문에 대한 좋은 대답을 본 것은 이번이 처음입니다.
— Robert Harvey

5
Path.GetFullPath ( "con.txt")는 유효한 파일 이름입니다.
— Christoffer

8
@Slaks 댓글을 남기기에는 너무 오래되었지만 -1로 투표 한 이유 때문에 여기에 하나를 남기고 싶습니다. Path.GetFullPath ()는 정상적으로 작동하는 것 같지만 경로가 "Z : \\\\\\\\ Hi \\\\\\ There"이면 유효한 절대 경로가 아니라 Path.GetFullPath입니다. (...) 결과를 제공합니다 : Z : \ Hi \ There 및 예외가 발생하지 않습니다. GetFullPath ()에서 반환 된 문자열과 다음과 같은 원래 문자열을 비교하여 약간 변경해야했습니다. private bool IsPathValid (string path) {try {string fullPath = Path.GetFullPath (path); return fullPath == path; } catch {return false;}}
— King King

4
@KingKing unix.stackexchange.com 의이 Linux 답변 에서 "여러 개의 슬래시가 허용되며 단일 슬래시와 동일합니다 .." Windows에서도 동일하게 관찰되었습니다 (UNC 경로의 선행 슬래시가 다르게 취급 될 수 있음). 이에 대한 증거를 보려면 명령 프롬프트에서 다음을 시도하십시오 cd C:\\\\\\\Windows\\\\\\\System32.. Windows의 경우이 동작을 문서화 한 신뢰할 수있는 소스를 찾을 수 없지만 물론 그에 대한 포인터는 환영합니다.
— DavidRR

20

나는 실제로 SLaks에 동의하지 않습니다. 그 솔루션은 저에게 효과적이지 않았습니다. 예상대로 예외가 발생하지 않았습니다. 그러나이 코드는 나를 위해 일했습니다.

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

62
유효한 경로는 반드시 문제가 여기에 요청 정확히 존재하는 디렉토리 ... 아니다
— Benlitz

1
질문은 존재하지 않을 수있는 경로 문자열의 유효성 검사와 관련이 있습니다.
— Mubashar 2013

이 방법이 맞다고 생각합니다. 예외는 예상되지 않아야합니다. 이 방법은 또한 주어진 경로에서 잘못된 문자를 확인합니다.
— Eugene Maksimov

Directory.Exists에는 유효한 경로가 필요하므로 "path"가 실제 경로가 아닌 경우이 조건은 자체적으로 예외를 발생시킵니다.
— M. Fawad Surosh

완전히 오답입니다! 어떻게 32 개의 찬성표를 받았는지 궁금합니다 (현재). 그들이 직면 한 문제에 대해 잘못된 곳을 찾고 있던 사람들에 의한 것임에 틀림 없다. 그리고 그들은 이것을 우연히 발견했다.
— Sнаđошƒаӽ

13

Path.GetFullPath는 아래 예외 만 제공합니다.

ArgumentException 경로가 길이가 0 인 문자열이거나 공백 만 포함하거나 GetInvalidPathChars에 정의 된 하나 이상의 잘못된 문자를 포함합니다. -또는-시스템이 절대 경로를 검색 할 수 없습니다.

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

2
@nawfal 참. 에서 파일, 경로 및 네임 스페이스 명명 MSDN에를 : "파일 이름에 대해 다음 예약 된 이름을 사용하지 마십시오 : CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8 및 LPT9. 또한 이러한 이름 뒤에 바로 확장자가 붙는 것을 피하십시오. 예를 들어 NUL.txt는 권장되지 않습니다. 자세한 내용은 네임 스페이스를 참조하십시오 . "
— DavidRR

이 "블랙리스트 aproach"는 모든 Windows 시스템에서 작동하지 않습니다. 예를 들어 그림 문자가 나타날 때 : en.wikipedia.org/wiki/Miscellaneous_Symbols_and_Pictographs
— Jan

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 :
경로가 길이가 0 인 문자열이거나 공백 만 포함하거나 하나 이상의 잘못된 문자를 포함합니다. 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.