문자열이 유효한 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.