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


165

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


정규식에 대한 답변을 사용하려면 정적 컴파일 정규식을 사용하는 것이 좋습니다.
AMissico

답변:


100

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

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

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


11
이것은 질문에 대답하지 않습니다. 유효한 파일 이름이 아닌 유효한 문자 (예 : "....", "CON", 수백 자의 문자열)로만 구성된 많은 문자열이 있습니다.
Dour High Arch

31
다른 사람은 MS가 각 개발자 대신 자신의 솔루션을 요리 해야하는 대신이 기능에 대한 시스템 수준 기능 / API를 제공하지 않는다고 실망 시켰습니까? 이것에 대한 충분한 이유가 있거나 MS 부분에 대한 감독이 있는지 궁금합니다.
Thomas Nguyen

@High 아치 : 질문 "파일 이름이된다는 점에서 C 번호 확인을위한 참조 응답 가능 (존재하지 않는 것이) 유효". (일부 영리한 사람이지만 ...이 하나의 찬성이 질문에 폐쇄)
mmmmmmmm

129

에서 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 한계를 초과 할 수 있음)

8
예약 된 파일 이름 포함 +1-이전 답변에서 누락되었습니다.
SqlRyan

2
"\\? \"구문을 사용하는 경우 "AUX"는 완벽하게 사용 가능한 파일 이름입니다. 물론, 그 구문을 사용하지 않는 프로그램은 실제 문제 (XP에서 테스트) ... 그것을 다루는이
user9876

9
위에서 언급 한 모든 조건에 대한 올바른 정규식은 다음과 같습니다.Regex unspupportedRegex = new Regex("(^(PRN|AUX|NUL|CON|COM[1-9]|LPT[1-9]|(\\.+)$)(\\..*)?$)|(([\\x00-\\x1f\\\\?*:\";|/<>])+)|(([\\. ]+)", RegexOptions.IgnoreCase);
whywhywhy

4
@whywhywhy 그 정규식에 추가 오프닝 괄호가 있다고 생각합니다. "(^ (PRN | AUX | NUL | CON | COM [1-9] | LPT [1-9] | (\\. +) $) (\\ .. *)? $) | (([[\\ x00-\\ x1f \\\\? * : \ "; ‌ | / <>]) +) | ([\\.] +)"저를 위해 일했습니다.
Wilky

4
이 답변에서 언급 한 동일한 기사를 읽었으며 COM0 및 LPT0도 허용되지 않는다는 실험을 통해 발견되었습니다. @dlf이 파일은 '.'로 시작하는 파일 이름으로 작동합니다.^(?!^(?:PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d)(?:\..+)?$)(?:\.*?(?!\.))[^\x00-\x1f\\?*:\";|\/<>]+(?<![\s.])$
mjohnsonengr

67

들어 닷넷 프레임 워크 이전 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


파일 이름이 아닌 경로 만 테스트하지 않습니까?
유진 카츠

30
문자열 strTheseAreInvalidFileNameChars = 새 문자열 (System.IO.Path.GetInvalidFileNameChars ()); 정규식 regFixFileName = 새로운 정규식 ( "["+ Regex.Escape (strTheseAreInvalidFileNameChars) + "]");
rao

2
사람들의 작은 연구는 놀라운 일이 될 것입니다. 변경 사항을 반영하도록 게시물을 업데이트했습니다.
Erik Philips

1
두 번째 코드는 컴파일되지 않습니다. "char []에서 문자열로 변환 할 수 없음
Paul Hunt

1
@AshkanMobayenKhiabani : InvalidPathChars는 사용되지 않지만 GetInvalidPathChars는 사용되지 않습니다.
IvanH

25

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


1
이것은 모든 제약 조건에 대해 테스트하는 유일한 것 같습니다. 왜 이것에 대해 다른 답변을 선택합니까?
gap

5
항상 작동하지는 않기 때문에 @gap. 예를 들어, CON에 액세스하려고하면 실제 파일이 아니더라도 종종 성공합니다.
안티몬

4
그래도 가능하면 예외를 throw하는 메모리 오버 헤드를 피하는 것이 좋습니다.
Owen Blacker

2
또한 액세스 권한이 없을 수도 있습니다. 예를 들어 존재하거나 존재하는 경우 읽을 수있는 경우에도 작성하여 테스트합니다.
CodeLurker

23

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

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();
    }

}

1
당신의 대답은 더 나은 여기에 맞게 수 : stackoverflow.com/questions/146134/...
nawfal

22

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

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


4
sPattern regex는 마침표로 시작하는 파일을 허용하지 않습니다. 그러나 MSDN은 "마침표를 이름의 첫 문자로 지정할 수 있습니다 (예 :".temp "). .gitignore를 올바른 파일 이름으로 만들기 위해 "\ .. *"를 제거합니다. :)
yar_shukan

(나는 이것을 점진적으로 개선하고 이전 의견을 삭제했습니다.) 이것은 ".gitignore", "..asdf", '<'및 '>'또는 엔을 허용하지 않기 때문에 답변의 정규 표현식보다 낫습니다. 부호, 끝에 공백이나 마침표를 허용하지 않음 (점으로 만 구성된 이름은 허용하지 않음) :@"^(?!(?:PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d)(?:\..+)?$)[^\x00-\x1F\xA5\\?*:\"";|\/<>]+(?<![\s.])$"
mjohnsonengr

이것은 테스트 한 모든 파일에 대해 실패합니다. C : \ Windows \ System32 \ msxml6.dll에 대해 실행하면 false가보고됩니다.
magicandre1981

@ magicandre1981 정규화 된 경로가 아니라 파일 이름 만 지정하면됩니다.
Scott Dorman 2016 년

그래도 전체 경로가 유효한지 확인해야합니다. 나는 지금 다른 해결책을 사용했다.
magicandre1981

18

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

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

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


10

Eugene Katz의 답변 단순화 :

bool IsFileNameCorrect(string fileName){
    return !fileName.Any(f=>Path.GetInvalidFileNameChars().Contains(f))
}

또는

bool IsFileNameCorrect(string fileName){
    return fileName.All(f=>!Path.GetInvalidFileNameChars().Contains(f))
}

"! fileName.Any (f => Path.GetInvalidFileNameChars (). Contains (f));"를 반환 하시겠습니까? ?
잭 그리핀

@JackGriffin 물론입니다! 세심한 감사합니다.
tmt

이 코드를 읽는 것이 매우 좋지만의 미안한 내부 요소를 고려해야합니다 Path.GetInvalidFileNameChars. 여기를보십시오 : referencesource.microsoft.com/#mscorlib/system/io/path.cs,289-의 각 문자 fileName에 대해 배열의 복제본이 생성됩니다.
Piotr Zierhoffer

"DD : \\\\\ AAA ..... AAAA". 유효하지 않지만 코드에는 유효합니다.
Ciccio Pasticcio

8

Microsoft Windows : Windows 커널은 1-31 범위의 문자 (예 : 0x01-0x1F)와 문자 "* : <>? \ |를 사용할 수 없습니다. NTFS는 각 경로 구성 요소 (디렉토리 또는 파일 이름)의 길이가 255 자이며 최대 약 32767 자 길이의 Windows 커널은 최대 259 자 길이의 경로 만 지원하며, Windows는 MS-DOS 장치 이름 AUX, CLOCK $, COM1, COM2, COM3, COM4, ​​COM5, COM6, COM7, COM8, COM9, CON, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9, NUL 및 PRN뿐만 아니라 확장명 (예 : AUX.txt)이있는 이름 (사용시 제외) 긴 UNC 경로 (예 : \. \ C : \ nul.txt 또는 \? \ D : \ aux \ con) (확장자가 제공되는 경우 CLOCK $이 사용될 수 있습니다.) 이러한 제한은 Windows에만 적용됩니다. 예를 들어 리눅스는 "* : <>? \ | NTFS에서도.

출처 : http://en.wikipedia.org/wiki/Filename


1
"CLOCK $"라는 파일을 만들 수 있습니다. Windows 7.
rory.ap

7

가능한 모든 문자를 명시 적으로 포함하는 대신 정규식을 사용하여 잘못된 문자가 있는지 확인한 다음 오류를보고 할 수 있습니다. 이상적으로 응용 프로그램은 사용자가 원하는대로 정확하게 파일 이름을 지정해야하며 오류가 발생하면 파울 링 만합니다.


6

문제는 경로 이름이 유효한 Windows 경로인지 또는 코드가 실행중인 시스템에서 유효한지 확인하려고한다는 것 입니다. ? 후자가 더 중요하다고 생각하므로 개인적으로 전체 경로를 분해하고 _mkdir을 사용하여 파일이 속한 디렉토리를 만든 다음 파일을 만들려고합니다.

이렇게하면 경로에 유효한 윈도우 문자 만 포함되어있을뿐만 아니라 실제로이 프로세스에서 쓸 수있는 경로를 나타내는 지 알 수 있습니다.


6

예외를 발생시키지 않고 파일 이름에서 유효하지 않은 문자를 제거하기 위해 이것을 사용합니다.

private static readonly Regex InvalidFileRegex = new Regex(
    string.Format("[{0}]", Regex.Escape(@"<>:""/\|?*")));

public static string SanitizeFileName(string fileName)
{
    return InvalidFileRegex.Replace(fileName, string.Empty);
}

5

또한 CON, PRN, AUX, NUL, COM # 및 기타 일부는 확장명을 가진 디렉토리의 법적 파일 이름이 아닙니다.


1
이것은 진실의 절반에 불과합니다. 유니 코드 버전의 CreateFile을 호출하는 경우 파일 이름 앞에 "\\? \"를 붙일 경우 이러한 이름으로 파일을 만들 수 있습니다.
Werner Henze

이 문장은 미스 LPT # 불완전
토마스 웰러


3

에서 MSDN , 여기에 허용되지 않는 문자의 목록은 다음과 같습니다

다음을 제외하고 확장 코드 세트 (128–255)의 유니 코드 문자 및 문자를 포함하여 이름에 현재 코드 페이지의 거의 모든 문자를 사용하십시오.

  • 다음 예약 문자는 허용되지 않습니다 : <> : "/ \ |? *
  • 정수 표현이 0에서 31 사이의 문자는 허용되지 않습니다.
  • 대상 파일 시스템이 허용하지 않는 다른 문자

2

또한 대상 파일 시스템이 중요합니다.

NTFS에서는 특정 파일에서 일부 파일을 만들 수 없습니다. 루트에서 EG $ Boot


2
NTFS 이름 지정 규칙 때문이 아니라 $Boot디렉토리에 이미 파일 이 존재 하기 때문 일까요?
Christian Hayter

2

이것은 이미 답변 된 질문이지만 "기타 옵션"을 위해서만 여기에 비 이상적인 질문이 있습니다.

(흐름 제어로 예외를 사용하는 것이 일반적으로 "나쁜 것"이기 때문에 비 이상적임)

public static bool IsLegalFilename(string name)
{
    try 
    {
        var fileInfo = new FileInfo(name);
        return true;
    }
    catch
    {
        return false;
    }
}

귀하의 예제는 CON 파일 (C : \ temp \ CON)에 대해 작동하지 않았습니다.
tcbrazil

그러나 'C : \ temp \ CON'은 유효한 파일 이름이 아닙니까? 왜 그렇지 않습니까?
Mark A. Donohoe

@MarqueIV-아니요, 유효하지 않습니다. 위의 모든 답변과 의견을 읽거나 직접 시도해보십시오.
rory.ap

@Jer, "/ example"은 합법적이지 않지만 메서드는을 반환합니다 true.
rory.ap

Aaaah ... 나는 'CON'부분을 놓쳤다. 이름 자체는 문자열 관점에서 유효 하지만 (이는 내가 언급 한 것입니다) 이제 CON은 예약 된 이름이므로 Windows 관점에서 유효하지 않습니다. 내 잘못이야.
Mark A. Donohoe

2

이 상황에서는 정규 표현식이 과도합니다. 당신은 사용할 수 String.IndexOfAny()와 함께 방법을 Path.GetInvalidPathChars()하고 Path.GetInvalidFileNameChars().

또한 두 Path.GetInvalidXXX()방법 모두 내부 배열을 복제하고 복제본을 반환합니다. 따라서이 작업을 많이 (수천 번) 수행하려는 경우 재사용을 위해 잘못된 chars 배열의 사본을 캐시 할 수 있습니다.


2

파일 이름 / 경로를 포함하는 문자열에 유효하지 않은 문자가 있는지 확인하려는 경우 가장 빠른 방법 Split()은 유효하지 않은 문자가있는 곳에서 파일 이름을 여러 배열로 나누는 것입니다. 결과가 1의 배열 인 경우 유효하지 않은 문자가 없습니다. :-)

var nameToTest = "Best file name \"ever\".txt";
bool isInvalidName = nameToTest.Split(System.IO.Path.GetInvalidFileNameChars()).Length > 1;

var pathToTest = "C:\\My Folder <secrets>\\";
bool isInvalidPath = pathToTest.Split(System.IO.Path.GetInvalidPathChars()).Length > 1;

LinqPad에서 파일 및 경로 이름 1,000,000 번에서 위에서 언급 한 다른 방법을 시도했습니다.

Split()~ 850ms 만 사용합니다 .

사용 Regex("[" + Regex.Escape(new string(System.IO.Path.GetInvalidPathChars())) + "]")은 약 6 초입니다.

더 복잡한 정규 표현식은 Path클래스 의 다양한 메소드를 사용하여 파일 이름을 얻고 내부 유효성 검사가 작업을 수행하도록하는 것과 같이 다른 옵션 중 일부와 마찬가지로 공정이 훨씬 나쁩니다 (대부분 예외 처리 오버 헤드로 인해).

백만 개의 파일 이름을 유효성 검사해야하는 경우가 많지 않으므로 대부분의 이러한 방법에는 단일 반복이 적합합니다. 그러나 유효하지 않은 문자 만 찾는 경우에도 여전히 효율적이고 효과적입니다.


1

파일 이름이 너무 길고 Windows 10 이전 환경에서 실행되는 경우 이러한 답변 중 대부분이 작동하지 않습니다. 마찬가지로 선행 또는 후행을 허용하는 것은 기술적으로 유효하지만 파일을 각각 보거나 삭제하기 어려운 경우 문제를 일으킬 수 있습니다.

유효한 파일 이름을 확인하기 위해 만든 유효성 검사 속성입니다.

public class ValidFileNameAttribute : ValidationAttribute
{
    public ValidFileNameAttribute()
    {
        RequireExtension = true;
        ErrorMessage = "{0} is an Invalid Filename";
        MaxLength = 255; //superseeded in modern windows environments
    }
    public override bool IsValid(object value)
    {
        //http://stackoverflow.com/questions/422090/in-c-sharp-check-that-filename-is-possibly-valid-not-that-it-exists
        var fileName = (string)value;
        if (string.IsNullOrEmpty(fileName)) { return true;  }
        if (fileName.IndexOfAny(Path.GetInvalidFileNameChars()) > -1 ||
            (!AllowHidden && fileName[0] == '.') ||
            fileName[fileName.Length - 1]== '.' ||
            fileName.Length > MaxLength)
        {
            return false;
        }
        string extension = Path.GetExtension(fileName);
        return (!RequireExtension || extension != string.Empty)
            && (ExtensionList==null || ExtensionList.Contains(extension));
    }
    private const string _sepChar = ",";
    private IEnumerable<string> ExtensionList { get; set; }
    public bool AllowHidden { get; set; }
    public bool RequireExtension { get; set; }
    public int MaxLength { get; set; }
    public string AllowedExtensions {
        get { return string.Join(_sepChar, ExtensionList); } 
        set {
            if (string.IsNullOrEmpty(value))
            { ExtensionList = null; }
            else {
                ExtensionList = value.Split(new char[] { _sepChar[0] })
                    .Select(s => s[0] == '.' ? s : ('.' + s))
                    .ToList();
            }
    } }

    public override bool RequiresValidationContext => false;
}

그리고 시험

[TestMethod]
public void TestFilenameAttribute()
{
    var rxa = new ValidFileNameAttribute();
    Assert.IsFalse(rxa.IsValid("pptx."));
    Assert.IsFalse(rxa.IsValid("pp.tx."));
    Assert.IsFalse(rxa.IsValid("."));
    Assert.IsFalse(rxa.IsValid(".pp.tx"));
    Assert.IsFalse(rxa.IsValid(".pptx"));
    Assert.IsFalse(rxa.IsValid("pptx"));
    Assert.IsFalse(rxa.IsValid("a/abc.pptx"));
    Assert.IsFalse(rxa.IsValid("a\\abc.pptx"));
    Assert.IsFalse(rxa.IsValid("c:abc.pptx"));
    Assert.IsFalse(rxa.IsValid("c<abc.pptx"));
    Assert.IsTrue(rxa.IsValid("abc.pptx"));
    rxa = new ValidFileNameAttribute { AllowedExtensions = ".pptx" };
    Assert.IsFalse(rxa.IsValid("abc.docx"));
    Assert.IsTrue(rxa.IsValid("abc.pptx"));
}

1

내 시도 :

using System.IO;

static class PathUtils
{
  public static string IsValidFullPath([NotNull] string fullPath)
  {
    if (string.IsNullOrWhiteSpace(fullPath))
      return "Path is null, empty or white space.";

    bool pathContainsInvalidChars = fullPath.IndexOfAny(Path.GetInvalidPathChars()) != -1;
    if (pathContainsInvalidChars)
      return "Path contains invalid characters.";

    string fileName = Path.GetFileName(fullPath);
    if (fileName == "")
      return "Path must contain a file name.";

    bool fileNameContainsInvalidChars = fileName.IndexOfAny(Path.GetInvalidFileNameChars()) != -1;
    if (fileNameContainsInvalidChars)
      return "File name contains invalid characters.";

    if (!Path.IsPathRooted(fullPath))
      return "The path must be absolute.";

    return "";
  }
}

Path.GetInvalidPathChars파일 및 디렉토리 이름에 유효하지 않은 완전한 문자 세트를 리턴하지 않으며 물론 더 많은 미묘함이 있기 때문에 이것은 완벽 하지 않습니다.

따라서이 방법을 보완 물로 사용합니다.

public static bool TestIfFileCanBeCreated([NotNull] string fullPath)
{
  if (string.IsNullOrWhiteSpace(fullPath))
    throw new ArgumentException("Value cannot be null or whitespace.", "fullPath");

  string directoryName = Path.GetDirectoryName(fullPath);
  if (directoryName != null) Directory.CreateDirectory(directoryName);
  try
  {
    using (new FileStream(fullPath, FileMode.CreateNew)) { }
    File.Delete(fullPath);
    return true;
  }
  catch (IOException)
  {
    return false;
  }
}

파일을 작성하려고 시도하고 예외가 있으면 false를 리턴합니다. 물론 파일을 만들어야하지만 가장 안전한 방법이라고 생각합니다. 또한 작성된 디렉토리는 삭제하지 않습니다.

첫 번째 방법을 사용하여 기본 유효성 검사를 수행 한 다음 경로를 사용할 때 예외를주의해서 처리 할 수도 있습니다.


0

Path.GetFullPath ()를 사용하는 것이 좋습니다.

string tagetFileFullNameToBeChecked;
try
{
  Path.GetFullPath(tagetFileFullNameToBeChecked)
}
catch(AugumentException ex)
{
  // invalid chars found
}

이 답변이 현재 문제를 해결하는 데 OP에 도움이되는 방법에 대한 답변이 포함 된 설명을 추가하십시오
ρяσѕρєя K

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

이론적으로 (문서에 따르면) 이것이 작동해야하지만 문제는 적어도 .NET Core 3.1에서는 발생하지만 그렇지 않습니다.
Michel Jansson

0

나는 누군가에게서이 아이디어를 얻었다. -누군지 몰라 OS가 무거운 작업을 수행하도록합니다.

public bool IsPathFileNameGood(string fname)
{
    bool rc = Constants.Fail;
    try
    {
        this._stream = new StreamWriter(fname, true);
        rc = Constants.Pass;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Problem opening file");
        rc = Constants.Fail;
    }
    return rc;
}

0

이 확인

static bool IsValidFileName(string name)
{
    return
        !string.IsNullOrWhiteSpace(name) &&
        name.IndexOfAny(Path.GetInvalidFileNameChars()) < 0 &&
        !Path.GetFullPath(name).StartsWith(@"\\.\");
}

유효하지 않은 문자 (와 이름을 필터링 <>:"/\|?*및 ASCII 0-31)뿐만 아니라 예약 DOS 장치 ( CON, NUL, COMx). 선행 공백과 모든 점 이름을 허용 Path.GetFullPath합니다. (앞 공백이있는 파일을 만드는 것이 시스템에서 성공합니다).


Windows 7에서 테스트 된 .NET Framework 4.7.1 사용


0

문자열에서 불법 문자를 확인하기위한 하나의 라이너 :

public static bool IsValidFilename(string testName) => !Regex.IsMatch(testName, "[" + Regex.Escape(new string(System.IO.Path.InvalidPathChars)) + "]");

0

제 생각에는이 질문에 대한 유일한 대답은 경로를 사용하고 OS와 파일 시스템이 경로를 확인하도록하는 것입니다. 그렇지 않으면 OS와 파일 시스템이 이미 사용하는 모든 유효성 검사 규칙을 다시 구현하고 있으며 아마도 규칙이 변경되면 해당 규칙과 일치하도록 코드를 변경해야합니다.


-1

윈도우 파일 이름은 그래서 정말조차되지 않을 수도 꽤 무제한 적있는 문제의 많은. Windows에서 허용하지 않는 문자는 다음과 같습니다.

\ / : * ? " < > |

해당 문자가 있는지 확인하는 표현식을 쉽게 작성할 수 있습니다. 더 나은 해결책은 사용자가 원하는대로 파일 이름을 지정하고 파일 이름이 붙어 있지 않은 경우 경고하는 것입니다.


또한 문자 <= 31은 금지됩니다.
안티몬
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.