[C#] 주어진 문자열이 Windows에서 유효한 / 유효한 파일 이름인지 어떻게 확인합니까?

응용 프로그램에 배치 파일 이름 바꾸기 기능을 포함하고 싶습니다. 사용자는 대상 파일 이름 패턴을 입력 할 수 있으며 (패턴에서 일부 와일드 카드를 바꾼 후) Windows에서 올바른 파일 이름인지 확인해야합니다. 나는 정규 표현식을 사용하려고 노력했다.[a-zA-Z0-9_]+ 다양한 언어 (예 : 움라우트 등)의 국가 별 문자가 많이 포함되어 있지 않습니다. 그러한 점검을 수행하는 가장 좋은 방법은 무엇입니까?



답변

Path.GetInvalidPathChars및 에서 잘못된 문자 목록을 얻을 수 있습니다 GetInvalidFileNameChars.

UPD : 정규 표현식에서이를 사용하는 방법에 대한 Steve Cooper의 제안 을 참조하십시오 .

UPD2 : MSDN의 비고 섹션에 따르면 “이 메서드에서 반환 된 배열에 파일 및 디렉터리 이름에 유효하지 않은 전체 문자 집합이 포함되어 있지는 않습니다.” sixlettervaliables제공하는 답변 은 더 자세히 설명되어 있습니다.


답변

에서 MSDN의 “이름 지정 파일 또는 디렉터리,” 여기 합법적 인 파일 이름은 Windows에서 무엇을위한 일반적인 규칙입니다 :

다음을 제외하고 현재 코드 페이지 (유니 코드 / ANSI 127 이상)에 문자를 사용할 수 있습니다.

  • < > : " / \ | ? *
  • 정수 표현이 0-31 인 문자 (ASCII 공간 미만)
  • 대상 파일 시스템이 허용하지 않는 다른 문자 (예 : 마침표 또는 공백)
  • DOS 이름 : CON, PRN, AUX, NUL, COM0, COM1, COM2, COM3, COM4, ​​COM5, COM6, COM7, COM8, COM9, LPT0, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9 (및 AUX.txt 등을 피하십시오)
  • 파일 이름은 모두 마침표입니다

몇 가지 선택 사항을 확인하십시오.

  • 파일 경로 (파일 이름 포함)는 260자를 초과 할 수 없습니다 ( \?\접두사를 사용하지 않음 )
  • 사용시 32,000자를 초과하는 유니 코드 파일 경로 (파일 이름 포함) \?\(접두사가 디렉토리 구성 요소를 확장하여 32,000 한계를 초과 할 수 있음)

답변

들어 닷넷 프레임 워크 이전 3.5 이 작동합니다 :

정규식 일치는 당신에게 어떤 길을 가져다 줄 것입니다. 다음은 System.IO.Path.InvalidPathChars상수를 사용하는 스 니펫입니다 .

bool IsValidFilename(string testName)
{
    Regex containsABadCharacter = new Regex("["
          + Regex.Escape(System.IO.Path.InvalidPathChars) + "]");
    if (containsABadCharacter.IsMatch(testName)) { return false; };

    // other checks for UNC, drive-path format, etc

    return true;
}

들어 닷넷 프레임 워크 3.0 이후 이 작동합니다 :

http://msdn.microsoft.com/en-us/library/system.io.path.getinvalidpathchars(v=vs.90).aspx

정규식 일치는 당신에게 어떤 길을 가져다 줄 것입니다. 다음은 System.IO.Path.GetInvalidPathChars()상수를 사용하는 스 니펫입니다 .

bool IsValidFilename(string testName)
{
    Regex containsABadCharacter = new Regex("["
          + Regex.Escape(new string(System.IO.Path.GetInvalidPathChars())) + "]");
    if (containsABadCharacter.IsMatch(testName)) { return false; };

    // other checks for UNC, drive-path format, etc

    return true;
}

당신이 알고 나면, 당신은 또한 다른 형식, 예를 들어 확인해야 c:\my\drive하고\\server\share\dir\file.ext


답변

그것을 사용하고 오류를 잡으십시오. 허용되는 집합은 파일 시스템이나 다른 버전의 Windows에서 변경 될 수 있습니다. 다시 말해, Windows가 이름을 좋아하는지 알고 싶다면 이름을 알려주고 알려주십시오.


답변

이 클래스는 파일 이름과 경로를 정리합니다. 처럼 사용

var myCleanPath = PathSanitizer.SanitizeFilename(myBadPath, ' ');

코드는 다음과 같습니다.

/// <summary>
/// Cleans paths of invalid characters.
/// </summary>
public static class PathSanitizer
{
    /// <summary>
    /// The set of invalid filename characters, kept sorted for fast binary search
    /// </summary>
    private readonly static char[] invalidFilenameChars;
    /// <summary>
    /// The set of invalid path characters, kept sorted for fast binary search
    /// </summary>
    private readonly static char[] invalidPathChars;

    static PathSanitizer()
    {
        // set up the two arrays -- sorted once for speed.
        invalidFilenameChars = System.IO.Path.GetInvalidFileNameChars();
        invalidPathChars = System.IO.Path.GetInvalidPathChars();
        Array.Sort(invalidFilenameChars);
        Array.Sort(invalidPathChars);

    }

    /// <summary>
    /// Cleans a filename of invalid characters
    /// </summary>
    /// <param name="input">the string to clean</param>
    /// <param name="errorChar">the character which replaces bad characters</param>
    /// <returns></returns>
    public static string SanitizeFilename(string input, char errorChar)
    {
        return Sanitize(input, invalidFilenameChars, errorChar);
    }

    /// <summary>
    /// Cleans a path of invalid characters
    /// </summary>
    /// <param name="input">the string to clean</param>
    /// <param name="errorChar">the character which replaces bad characters</param>
    /// <returns></returns>
    public static string SanitizePath(string input, char errorChar)
    {
        return Sanitize(input, invalidPathChars, errorChar);
    }

    /// <summary>
    /// Cleans a string of invalid characters.
    /// </summary>
    /// <param name="input"></param>
    /// <param name="invalidChars"></param>
    /// <param name="errorChar"></param>
    /// <returns></returns>
    private static string Sanitize(string input, char[] invalidChars, char errorChar)
    {
        // null always sanitizes to null
        if (input == null) { return null; }
        StringBuilder result = new StringBuilder();
        foreach (var characterToTest in input)
        {
            // we binary search for the character in the invalid set. This should be lightning fast.
            if (Array.BinarySearch(invalidChars, characterToTest) >= 0)
            {
                // we found the character in the array of 
                result.Append(errorChar);
            }
            else
            {
                // the character was not found in invalid, so it is valid.
                result.Append(characterToTest);
            }
        }

        // we're done.
        return result.ToString();
    }

}


답변

이것이 내가 사용하는 것입니다 :

    public static bool IsValidFileName(this string expression, bool platformIndependent)
    {
        string sPattern = @"^(?!^(PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d|\..*)(\..+)?$)[^\x00-\x1f\\?*:\"";|/]+$";
        if (platformIndependent)
        {
           sPattern = @"^(([a-zA-Z]:|\\)\\)?(((\.)|(\.\.)|([^\\/:\*\?""\|<>\. ](([^\\/:\*\?""\|<>\. ])|([^\\/:\*\?""\|<>]*[^\\/:\*\?""\|<>\. ]))?))\\)*[^\\/:\*\?""\|<>\. ](([^\\/:\*\?""\|<>\. ])|([^\\/:\*\?""\|<>]*[^\\/:\*\?""\|<>\. ]))?$";
        }
        return (Regex.IsMatch(expression, sPattern, RegexOptions.CultureInvariant));
    }

첫 번째 패턴은 Windows 플랫폼에 대해서만 유효하지 않은 / 잘못된 파일 이름 및 문자를 포함하는 정규식을 작성합니다. 두 번째는 동일하지만 이름이 모든 플랫폼에 합법적임을 보장합니다.


답변

한 가지 코너 케이스를 염두에두면 처음 알게되었을 때 놀랐습니다. Windows는 파일 이름에 공백 문자를 허용합니다! 예를 들어 다음은 Windows에서 합법적이고 고유 한 파일 이름 (따옴표 제외)입니다.

"file.txt"
" file.txt"
"  file.txt"

이것에서 한 가지 탈취 : 파일 이름 문자열에서 선행 / 후행 공백을 자르는 코드를 작성할 때주의하십시오.