답변:
Path.GetInvalidPathChars
및 에서 잘못된 문자 목록을 얻을 수 있습니다 GetInvalidFileNameChars
.
UPD : 정규 표현식에서이를 사용하는 방법에 대한 Steve Cooper의 제안 을 참조하십시오 .
UPD2 : MSDN의 비고 섹션에 따르면 "이 메서드에서 반환 된 배열에 파일 및 디렉터리 이름에 유효하지 않은 전체 문자 집합이 포함되어 있지는 않습니다." sixlettervaliables 가 제공하는 답변 은 더 자세히 설명되어 있습니다.
에서 MSDN의 "이름 지정 파일 또는 디렉터리," 여기 합법적 인 파일 이름은 Windows에서 무엇을위한 일반적인 규칙입니다 :
다음을 제외하고 현재 코드 페이지 (유니 코드 / ANSI 127 이상)에 문자를 사용할 수 있습니다.
<
>
:
"
/
\
|
?
*
몇 가지 선택 사항을 확인하십시오.
\?\
접두사를 사용하지 않음 )\?\
(접두사가 디렉토리 구성 요소를 확장하여 32,000 한계를 초과 할 수 있음)Regex unspupportedRegex = new Regex("(^(PRN|AUX|NUL|CON|COM[1-9]|LPT[1-9]|(\\.+)$)(\\..*)?$)|(([\\x00-\\x1f\\\\?*:\";|/<>])+)|(([\\. ]+)", RegexOptions.IgnoreCase);
^(?!^(?:PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d)(?:\..+)?$)(?:\.*?(?!\.))[^\x00-\x1f\\?*:\";|\/<>]+(?<![\s.])$
들어 닷넷 프레임 워크 이전 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 플랫폼에 대해서만 유효하지 않은 / 잘못된 파일 이름 및 문자를 포함하는 정규식을 작성합니다. 두 번째는 동일하지만 이름이 모든 플랫폼에 합법적임을 보장합니다.
@"^(?!(?:PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d)(?:\..+)?$)[^\x00-\x1F\xA5\\?*:\"";|\/<>]+(?<![\s.])$"
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))
}
Path.GetInvalidFileNameChars
. 여기를보십시오 : referencesource.microsoft.com/#mscorlib/system/io/path.cs,289-의 각 문자 fileName
에 대해 배열의 복제본이 생성됩니다.
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에서도.
또한 CON, PRN, AUX, NUL, COM # 및 기타 일부는 확장명을 가진 디렉토리의 법적 파일 이름이 아닙니다.
다른 답변을 보완하기 위해 고려해야 할 몇 가지 추가 사례가 있습니다.
이름에 '['또는 ']'문자가 포함 된 파일에 통합 문서를 저장하면 Excel에 문제가있을 수 있습니다. 자세한 내용은 http://support.microsoft.com/kb/215205 를 참조 하십시오 .
Sharepoint에는 전체 추가 제한 사항이 있습니다. 자세한 내용은 http://support.microsoft.com/kb/905231 을 참조 하십시오 .
또한 대상 파일 시스템이 중요합니다.
NTFS에서는 특정 파일에서 일부 파일을 만들 수 없습니다. 루트에서 EG $ Boot
$Boot
디렉토리에 이미 파일 이 존재 하기 때문 일까요?
이것은 이미 답변 된 질문이지만 "기타 옵션"을 위해서만 여기에 비 이상적인 질문이 있습니다.
(흐름 제어로 예외를 사용하는 것이 일반적으로 "나쁜 것"이기 때문에 비 이상적임)
public static bool IsLegalFilename(string name)
{
try
{
var fileInfo = new FileInfo(name);
return true;
}
catch
{
return false;
}
}
true
.
파일 이름 / 경로를 포함하는 문자열에 유효하지 않은 문자가 있는지 확인하려는 경우 가장 빠른 방법 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
클래스 의 다양한 메소드를 사용하여 파일 이름을 얻고 내부 유효성 검사가 작업을 수행하도록하는 것과 같이 다른 옵션 중 일부와 마찬가지로 공정이 훨씬 나쁩니다 (대부분 예외 처리 오버 헤드로 인해).
백만 개의 파일 이름을 유효성 검사해야하는 경우가 많지 않으므로 대부분의 이러한 방법에는 단일 반복이 적합합니다. 그러나 유효하지 않은 문자 만 찾는 경우에도 여전히 효율적이고 효과적입니다.
파일 이름이 너무 길고 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"));
}
내 시도 :
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를 리턴합니다. 물론 파일을 만들어야하지만 가장 안전한 방법이라고 생각합니다. 또한 작성된 디렉토리는 삭제하지 않습니다.
첫 번째 방법을 사용하여 기본 유효성 검사를 수행 한 다음 경로를 사용할 때 예외를주의해서 처리 할 수도 있습니다.
Path.GetFullPath ()를 사용하는 것이 좋습니다.
string tagetFileFullNameToBeChecked;
try
{
Path.GetFullPath(tagetFileFullNameToBeChecked)
}
catch(AugumentException ex)
{
// invalid chars found
}
나는 누군가에게서이 아이디어를 얻었다. -누군지 몰라 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;
}
이 확인
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 사용