В C# проверьте, что имя файла * возможно * действительное (не то, что оно существует)

Есть ли в пространстве имен System.IO метод, который проверяет правильность имени файла?

Например, C:\foo\bar будет проверять, а :"~-* - нет.

Или, что немного сложнее, X:\foo\bar проверит, есть ли в системе привод X:, но иначе не стал бы.

Полагаю, я мог бы написать такой метод сам, но мне больше интересен встроенный.

Требует ли «не то, что он выходит», проверка того, что папки существуют, или нет? Какие границы проверки? Диск существует и все символы действительны?

BenAlabaster 08.01.2009 00:14
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
128
1
119 964
14

Ответы 14

Вы можете получить список недопустимых символов из Path.GetInvalidPathChars и GetInvalidFileNameChars, как описано в этот вопрос.

Как заметил jberger, есть некоторые другие символы, которые не включены в ответ от этого метода. Для получения более подробной информации о платформе Windows, взгляните на Именование файлов, путей и пространств имен в MSDN,

Как и у Мика указывает на то, есть Directory.GetLogicalDrives для получения списка допустимых дисков.

«Не гарантируется, что массив, возвращаемый этим методом, содержит набор символов полный, недопустимый в именах файлов и каталогов». Замечания

Jake Berger 29.06.2011 01:22

Позвольте мне повторить это. Одних персонажей недостаточно, чтобы знать, что это действительно так. Например: допустимо ноль или один раз, но НЕ ВСЕГДА второй символ в строке, если он существует!

Robert P 14.03.2013 21:17

Это не так. Некоторые имена также запрещены, а не только определенные символы.

Wouter Schut 19.05.2017 12:45

«ДД: \\\\\ AAA ..... AAAA». Недействительно, но для вашего кода это так.

Ciccio Pasticcio 02.07.2020 23:06

Просто делать;

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 предположить, что файл находится относительно текущего рабочего каталога, что может быть не тем, что вам нужно.

Echilon 02.01.2010 15:14

Я улучшил это решение, используя bOk = System.IO.Path.IsPathRooted (fileName); вместо bOk = true;

jing 24.09.2013 11:12

При этом не обнаруживается недопустимое имя файла, содержащее '/'.

Marc 15.10.2013 10:53

Вы можете добавить проверку для вашего имени файла, содержащего любой из символов в массиве, возвращаемом char [] badChars = Path.GetInvalidFileNameChars ();

Jon Dosmann 12.02.2015 21:27

Обратите внимание, что для оценки пути UNC, такого как \\drive\file.txt, потребуется много времени, поскольку конструктор отправляет пакеты SMB для получения всех свойств FileInfo.

bytecode77 18.07.2018 22:03

Такие вещи, как PRN, AUX, LPT1, COM1, NUL и т. д. Могут быть сопоставлены с именем устройства. Например. Тогда C:\COM1 - это \\.\COM1, это последовательный порт, а не файл.

Thomas Weller 30.10.2018 12:37

Используйте статический GetInvalidFileNameChars метод на Path класс в System.IO пространство имен, чтобы определить, какие символы недопустимы в имени файла.

Для этого в пути вызовите статический GetInvalidPathChars метод того же класса.

Чтобы определить, действителен ли корень пути, вы должны вызвать статический GetPathRoot метод в классе Path, чтобы получить корень, а затем использовать Directory класс, чтобы определить, действителен ли он. Затем вы можете нормально проверить оставшуюся часть пути.

«Не гарантируется, что массив, возвращаемый этим методом, содержит набор символов полный, недопустимый в именах файлов и каталогов». Замечания

Jake Berger 29.06.2011 01:23

Расширяя сказанное Робертом выше ... Использование GetInvalidPathChars само по себе не совсем корректный способ проверить правильность строки, представляющей путь. Этот метод возвращает символы «control» и «> <|, означающие, что эта строка (без заключительных двойных кавычек) действительна« C: \ Folder1 \ Folder * 2 \ Fol: der3 ». Теперь откройте проводник Windows или командную консоль. и попытайтесь создать эту структуру папок и дайте мне знать, что происходит ... Вам нужно разбить путь на его компоненты и проверить действительный указатель тома и проверить каждый компонент каталога как допустимое имя файла

PMBottas 25.05.2013 05:41

Даже если имя файла действительное, вы все равно можете захотеть записать его на touch, чтобы убедиться, что у пользователя есть разрешение на запись.

Если вы не будете загружать диск сотнями файлов за короткий период времени, я думаю, что создание пустого файла - разумный подход.

Если вам действительно нужно что-то более легкое, например, просто проверка на недопустимые символы, сравните свое имя файла с Path.GetInvalidFileNameChars ().

Вероятно, лучший способ - создать собственный метод, сочетающий комбинацию регулярного выражения и небольшого поиска в вашей файловой системе (например, чтобы увидеть диски)

Я не знаю ничего из коробки, что могло бы просто подтвердить все это для вас, однако класс Path в .NET может вам очень помочь.

Во-первых, в нем есть:

char[] invalidChars = Path.GetInvalidFileNameChars(); //returns invalid charachters

или же:

Path.GetPathRoot(string); // will return the root.

Некоторые методы System.IO.Path будут вызывать исключения, если путь или имя файла недействительны:

  • Путь.IsPathRooted ()
  • Путь.GetFileName ()

http://msdn.microsoft.com/en-us/library/system.io.path_methods.aspx

Это не похоже на правду, по крайней мере, в Mono (например, в Unity). Я использую поддельный путь «Bogus \\ Invalid! / No: such? File! * @ #!», И IsPathRooted возвращает true, GetFileName возвращает часть после косой черты, а FileInfo полностью не генерирует исключение. (Однако вызов GetDirectories в каталоге вызывает исключение, так что, возможно, это ответ в моем случае.)

Joe Strout 24.08.2016 18:15

Это не работает. Path.GetFileName ("* xxx?") Вернет "* xxx?" без исключения. Также не забывайте о зарезервированных именах файлов, которые будут некорректными для новых файлов. В Windows это "prn", "con" и т. д.

epox 21.04.2017 11:03

Это неверный ответ.

rory.ap 25.08.2017 21:01

В пространстве имен 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/…

Eugene Katz 08.01.2009 00:30

«regexString» должно выглядеть так: строка regex String Path = "[" + Regex.Escape (новая строка (System.IO.Path.GetInvalidPathChars ())) + "]";

panako 05.02.2014 14:59

Что насчет @"C:\\Windows" (действительно с двойной обратной косой чертой)? Проводник говорит, что это недопустимый путь, но вы не проверяете это.

KnorxThieus 25.08.2017 16:31

Это даст вам диски на машине:

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 файлом.

drowa 09.02.2018 23:18

Кроме того, такие вещи, как file:///a, будут приняты вашим методом как допустимый путь.

drowa 09.02.2018 23:24

Также не работает, если в конце стоит вопросительный знак. C:\\foo\\bar??

Lion King 08.03.2018 12:33

Думаю, уже поздно отвечать, но ... :) в случае пути с именем тома вы можете написать что-то вроде этого:

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

Другие вопросы по теме