Есть ли в пространстве имен System.IO метод, который проверяет правильность имени файла?
Например, C:\foo\bar будет проверять, а :"~-* - нет.
Или, что немного сложнее, X:\foo\bar проверит, есть ли в системе привод X:, но иначе не стал бы.
Полагаю, я мог бы написать такой метод сам, но мне больше интересен встроенный.





Вы можете получить список недопустимых символов из Path.GetInvalidPathChars и GetInvalidFileNameChars, как описано в этот вопрос.
Как заметил jberger, есть некоторые другие символы, которые не включены в ответ от этого метода. Для получения более подробной информации о платформе Windows, взгляните на Именование файлов, путей и пространств имен в MSDN,
Как и у Мика указывает на то, есть Directory.GetLogicalDrives для получения списка допустимых дисков.
«Не гарантируется, что массив, возвращаемый этим методом, содержит набор символов полный, недопустимый в именах файлов и каталогов». Замечания
Позвольте мне повторить это. Одних персонажей недостаточно, чтобы знать, что это действительно так. Например: допустимо ноль или один раз, но НЕ ВСЕГДА второй символ в строке, если он существует!
Это не так. Некоторые имена также запрещены, а не только определенные символы.
«ДД: \\\\\ AAA ..... AAAA». Недействительно, но для вашего кода это так.
Просто делать;
System.IO.FileInfo fi = null;
try {
fi = new System.IO.FileInfo(fileName);
}
catch (ArgumentException) { }
catch (System.IO.PathTooLongException) { }
catch (NotSupportedException) { }
if (ReferenceEquals(fi, null)) {
// file name is not valid
} else {
// file name is valid... May check for existence by calling fi.Exists.
}
Для создания экземпляра FileInfo файл не должен существовать.
Будьте осторожны с FileInfo. Любая строка, даже если это всего лишь одна буква, является допустимым аргументом в конструкторе, но простая попытка новой FileInfo (pathTheuserEntered) заставит FileInfo предположить, что файл находится относительно текущего рабочего каталога, что может быть не тем, что вам нужно.
Я улучшил это решение, используя bOk = System.IO.Path.IsPathRooted (fileName); вместо bOk = true;
При этом не обнаруживается недопустимое имя файла, содержащее '/'.
Вы можете добавить проверку для вашего имени файла, содержащего любой из символов в массиве, возвращаемом char [] badChars = Path.GetInvalidFileNameChars ();
Обратите внимание, что для оценки пути UNC, такого как \\drive\file.txt, потребуется много времени, поскольку конструктор отправляет пакеты SMB для получения всех свойств FileInfo.
Такие вещи, как PRN, AUX, LPT1, COM1, NUL и т. д. Могут быть сопоставлены с именем устройства. Например. Тогда C:\COM1 - это \\.\COM1, это последовательный порт, а не файл.
Используйте статический GetInvalidFileNameChars метод на Path класс в System.IO пространство имен, чтобы определить, какие символы недопустимы в имени файла.
Для этого в пути вызовите статический GetInvalidPathChars метод того же класса.
Чтобы определить, действителен ли корень пути, вы должны вызвать статический GetPathRoot метод в классе Path, чтобы получить корень, а затем использовать Directory класс, чтобы определить, действителен ли он. Затем вы можете нормально проверить оставшуюся часть пути.
«Не гарантируется, что массив, возвращаемый этим методом, содержит набор символов полный, недопустимый в именах файлов и каталогов». Замечания
Расширяя сказанное Робертом выше ... Использование GetInvalidPathChars само по себе не совсем корректный способ проверить правильность строки, представляющей путь. Этот метод возвращает символы «control» и «> <|, означающие, что эта строка (без заключительных двойных кавычек) действительна« C: \ Folder1 \ Folder * 2 \ Fol: der3 ». Теперь откройте проводник Windows или командную консоль. и попытайтесь создать эту структуру папок и дайте мне знать, что происходит ... Вам нужно разбить путь на его компоненты и проверить действительный указатель тома и проверить каждый компонент каталога как допустимое имя файла
Даже если имя файла действительное, вы все равно можете захотеть записать его на touch, чтобы убедиться, что у пользователя есть разрешение на запись.
Если вы не будете загружать диск сотнями файлов за короткий период времени, я думаю, что создание пустого файла - разумный подход.
Если вам действительно нужно что-то более легкое, например, просто проверка на недопустимые символы, сравните свое имя файла с Path.GetInvalidFileNameChars ().
Вероятно, лучший способ - создать собственный метод, сочетающий комбинацию регулярного выражения и небольшого поиска в вашей файловой системе (например, чтобы увидеть диски)
Я не знаю ничего из коробки, что могло бы просто подтвердить все это для вас, однако класс Path в .NET может вам очень помочь.
Во-первых, в нем есть:
char[] invalidChars = Path.GetInvalidFileNameChars(); //returns invalid charachters
или же:
Path.GetPathRoot(string); // will return the root.
Некоторые методы System.IO.Path будут вызывать исключения, если путь или имя файла недействительны:
http://msdn.microsoft.com/en-us/library/system.io.path_methods.aspx
Это не похоже на правду, по крайней мере, в Mono (например, в Unity). Я использую поддельный путь «Bogus \\ Invalid! / No: such? File! * @ #!», И IsPathRooted возвращает true, GetFileName возвращает часть после косой черты, а FileInfo полностью не генерирует исключение. (Однако вызов GetDirectories в каталоге вызывает исключение, так что, возможно, это ответ в моем случае.)
Это не работает. Path.GetFileName ("* xxx?") Вернет "* xxx?" без исключения. Также не забывайте о зарезервированных именах файлов, которые будут некорректными для новых файлов. В Windows это "prn", "con" и т. д.
Это неверный ответ.
В пространстве имен System.IO можно использовать несколько методов:
Directory.GetLogicalDrives() // Returns an array of strings like "c:\"
Path.GetInvalidFileNameChars() // Returns an array of characters that cannot be used in a file name
Path.GetInvalidPathChars() // Returns an array of characters that cannot be used in a path.
Как было предложено, вы могли бы сделать это:
bool IsValidFilename(string testName) {
string regexString = "[" + Regex.Escape(Path.GetInvalidPathChars()) + "]";
Regex containsABadCharacter = new Regex(regexString);
if (containsABadCharacter.IsMatch(testName)) {
return false;
}
// Check for drive
string pathRoot = Path.GetPathRoot(testName);
if (Directory.GetLogicalDrives().Contains(pathRoot)) {
// etc
}
// other checks for UNC, drive-path format, etc
return true;
}
Я не собираюсь голосовать против, но вы действительно должны отдать должное при использовании примеров кода от других людей, особенно когда это не совсем правильно. stackoverflow.com/questions/62771/…
«regexString» должно выглядеть так: строка regex String Path = "[" + Regex.Escape (новая строка (System.IO.Path.GetInvalidPathChars ())) + "]";
Что насчет @"C:\\Windows" (действительно с двойной обратной косой чертой)? Проводник говорит, что это недопустимый путь, но вы не проверяете это.
Это даст вам диски на машине:
System.IO.DriveInfo.GetDrives()
Эти два метода помогут вам проверить плохие символы:
System.IO.Path.GetInvalidFileNameChars();
System.IO.Path.GetInvalidPathChars();
Мне повезло с использованием регулярных выражений, как показали другие.
Следует иметь в виду, что Windows, по крайней мере, запрещает некоторые имена файлов, которые в противном случае содержат недопустимые символы. На ум приходят несколько: com, nul, prn.
У меня его сейчас нет, но у меня есть регулярное выражение, которое учитывает это имя файла. Если хочешь, я могу опубликовать его, в противном случае я уверен, что ты найдешь его так же, как и я: в Google.
-Джей
Вы можете использовать класс System.Uri. Класс Uri полезен не только для веб-URL, он также обрабатывает пути в файловой системе. Используйте метод Uri.TryCreate, чтобы определить, является ли путь корневым, затем используйте свойство IsLoopback, чтобы определить, ссылается ли Uri на локальный компьютер.
Вот простой метод, который определяет, является ли строка допустимым, локальным и корневым путем к файлу.
public bool IsPathValidRootedLocal(String pathString) {
Uri pathUri;
Boolean isValidUri = Uri.TryCreate(pathString, UriKind.Absolute, out pathUri);
return isValidUri && pathUri != null && pathUri.IsLoopback;
}
Я уверен, что это сработает.
Вы также должны проверить, является ли Uri.Schema файлом.
Кроме того, такие вещи, как file:///a, будут приняты вашим методом как допустимый путь.
Также не работает, если в конце стоит вопросительный знак. C:\\foo\\bar??
Думаю, уже поздно отвечать, но ... :) в случае пути с именем тома вы можете написать что-то вроде этого:
using System;
using System.Linq;
using System.IO;
// ...
var drives = Environment.GetLogicalDrives();
var invalidChars = Regex.Replace(new string(Path.GetInvalidFileNameChars()), "[\\\/]", "");
var drive = drives.FirstOrDefault(d => filePath.StartsWith(d));
if (drive != null) {
var fileDirPath = filePath.Substring(drive.Length);
if (0 < fileDirPath.Length) {
if (fileDirPath.IndexOfAny(invalidChars.ToCharArray()) == -1) {
if (Path.Combine(drive, fileDirPath) != drive) {
// path correct and we can proceed
}
}
}
}
Думал, что опубликую решение, которое я сколотил из кусочков ответов, которые я нашел после поиска надежного решения той же проблемы. Надеюсь, это поможет кому-то другому.
using System;
using System.IO;
//..
public static bool ValidateFilePath(string path, bool RequireDirectory, bool IncludeFileName, bool RequireFileName = false)
{
if (string.IsNullOrEmpty(path)) { return false; }
string root = null;
string directory = null;
string filename = null;
try
{
// throw ArgumentException - The path parameter contains invalid characters, is empty, or contains only white spaces.
root = Path.GetPathRoot(path);
// throw ArgumentException - path contains one or more of the invalid characters defined in GetInvalidPathChars.
// -or- String.Empty was passed to path.
directory = Path.GetDirectoryName(path);
// path contains one or more of the invalid characters defined in GetInvalidPathChars
if (IncludeFileName) { filename = Path.GetFileName(path); }
}
catch (ArgumentException)
{
return false;
}
// null if path is null, or an empty string if path does not contain root directory information
if (String.IsNullOrEmpty(root)) { return false; }
// null if path denotes a root directory or is null. Returns String.Empty if path does not contain directory information
if (String.IsNullOrEmpty(directory)) { return false; }
if (RequireFileName)
{
// if the last character of path is a directory or volume separator character, this method returns String.Empty
if (String.IsNullOrEmpty(filename)) { return false; }
// check for illegal chars in filename
if (filename.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0) { return false; }
}
return true;
}
Попробуйте этот метод, который попытается охватить все возможные сценарии исключений. Это будет работать почти для всех путей, связанных с Windows.
/// <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;
}
Требует ли «не то, что он выходит», проверка того, что папки существуют, или нет? Какие границы проверки? Диск существует и все символы действительны?