Как проверить, является ли данная строка допустимым / допустимым именем файла в Windows?

165

Я хочу включить функцию переименования командного файла в мое приложение. Пользователь может ввести шаблон имени файла назначения и (после замены некоторых шаблонов в шаблоне) мне нужно проверить, будет ли это допустимое имя файла в Windows. Я пытался использовать регулярное выражение, как, [a-zA-Z0-9_]+но оно не включает в себя много национальных символов из разных языков (например, умляуты и так далее). Каков наилучший способ сделать такую ​​проверку?

Томаша
источник
Я предлагаю использовать статический скомпилированный Regex, если вы собираетесь использовать любой из ответов с Regex ..
AMissico

Ответы:

100

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

UPD: см . Предложение Стива Купера о том, как использовать их в регулярном выражении.

UPD2: обратите внимание, что в соответствии с разделом «Примечания» в MSDN «Массив, возвращаемый этим методом, не обязательно содержит полный набор символов, недопустимых в именах файлов и каталогов». Ответ, предоставленный Sixlettervaliables, входит в более подробную информацию.

Евгений Кац
источник
11
Это не отвечает на вопрос; Есть много строк, состоящих только из допустимых символов (например, «....», «CON», строки длиной в сотни символов), которые не являются допустимыми именами файлов.
Dour High Arch
31
Кто-нибудь еще разочарован тем, что MS не предоставляет функции / API системного уровня для этой возможности вместо того, чтобы каждый разработчик готовил свое собственное решение? Интересно, есть ли для этого веская причина или просто недосмотр со стороны MS.
Томас Нгуен
@High Arch: см. Ответ на вопрос «В C # проверьте, что имя файла возможно (не то, что оно существует)». (Хотя некоторые умные парни закрыли этот вопрос в пользу этого ...)
мммммммм
129

В MSDN «Наименование файла или каталога» приведены общие соглашения о том, что такое допустимое имя файла под Windows:

Вы можете использовать любой символ в текущей кодовой странице (Unicode / 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 символов (без \?\префикса)
  • Пути к файлам Unicode (включая имя файла), содержащие более 32 000 символов при использовании \?\(обратите внимание, что префикс может расширять компоненты каталога и приводить к переполнению лимита в 32 000)
user7116
источник
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);
почему, почему
4
@whywhywhy Я думаю, у тебя есть дополнительная открывающая скобка в этом регулярном выражении. «(^ (PRN | AUX | NUL | CON | COM [1-9] | LPT [1-9] | (\\ +) $) (\\ .. *) $.?) | (([\\ x00 - \\ x1f \\\\? *: \ "; ‌ | / <>]) +) | ([\\.] +)" работал для меня.
Вилки
4
Я прочитал ту же статью, упомянутую в этом ответе, и обнаружил в результате экспериментов, что COM0 и LPT0 также не разрешены. @dlf это работает с именами файлов, которые начинаются с '.':^(?!^(?:PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d)(?:\..+)?$)(?:\.*?(?!\.))[^\x00-\x1f\\?*:\";|\/<>]+(?<![\s.])$
mjohnsonengr
67

Для .Net Framework до 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;
}

Для .Net Frameworks после 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
string strTheseAreInvalidFileNameChars = новая строка (System.IO.Path.GetInvalidFileNameChars ()); Regex regFixFileName = new Regex ("[" + Regex.Escape (strTheseAreInvalidFileNameChars) + "]");
Рао
2
Небольшое исследование людей сделало бы чудеса. Я обновил пост, чтобы отразить изменения.
Эрик Филипс
1
2-й кусок кода не компилируется. "Невозможно преобразовать символ [] в строку
Пол Хант,
1
@AshkanMobayenKhiabani: InvalidPathChars устарела, а GetInvalidPathChars - нет.
IvanH
25

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


источник
1
Кажется, это единственный тест, который проверяет все ограничения. Почему другие ответы выбираются из-за этого?
разрыв
5
@ разрыв, потому что это не всегда работает. Например, попытка доступа к CON часто будет успешной, даже если это не настоящий файл.
Сурьма
4
Тем не менее, всегда лучше избегать излишних затрат памяти при создании исключения, если это возможно.
Оуэн Блэк
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 не позволяет файлам начинаться с символа точки. Но MSDN говорит: «Допустимо указывать точку в качестве первого символа имени. Например,« .temp »». Я бы удалил "\ .. *", чтобы сделать правильное имя файла
.gitignore
(Я постепенно улучшал это и удалял предыдущие комментарии, которые я оставил) Этот лучше, чем регулярное выражение ответа, потому что он позволяет использовать «.gitignore», «..asdf», не разрешает «<» и «>» или иену подписывать и не допускать пробела или точки в конце (что запрещает имена, состоящие только из точек):@"^(?!(?:PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d)(?:\..+)?$)[^\x00-\x1F\xA5\\?*:\"";|\/<>]+(?<![\s.])$"
mjohnsonengr
это не работает для всех файлов, которые я тестировал. запуск его для C: \ Windows \ System32 \ msxml6.dll сообщает о ложном.
magicandre1981
@ magicandre1981 Вам нужно дать ему только имя файла, а не полный путь.
Скотт Дорман
хорошо, но мне нужно проверить, допустим ли полный путь. Я использовал сейчас другое решение.
magicandre1981
18

Нужно помнить один угловой случай, который удивил меня, когда я впервые узнал об этом: Windows позволяет вводить пробелы в именах файлов! Например, ниже приведены все допустимые и разные имена файлов в Windows (без кавычек):

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

Один из выводов из этого: будьте осторожны при написании кода, который удаляет начальные / конечные пробелы из строки имени файла.

Джон Шнайдер
источник
10

Упрощение ответа Евгения Каца:

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

Или

bool IsFileNameCorrect(string fileName){
    return fileName.All(f=>!Path.GetInvalidFileNameChars().Contains(f))
}
TMT
источник
Возможно, вы имели в виду: "return! FileName.Any (f => Path.GetInvalidFileNameChars (). Contains (f));" ?
Джек Гриффин
@JackGriffin Конечно! Спасибо за вашу внимательность.
TMT
В то время как этот код очень приятен для чтения, мы должны принять во внимание сожаления о внутренностях Path.GetInvalidFileNameChars. Посмотрите здесь: referenceource.microsoft.com/#mscorlib/system/io/path.cs,289 - для каждого вашего символа fileNameсоздается клон массива.
Петр Циргофер
"DD: \\\\\ AAA ..... АААА". Не верно, но для вашего кода это так.
Чиччо Пастиччо
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 - Linux, например, позволяет использовать "*: <>? \ | даже в NTFS.

Источник: http://en.wikipedia.org/wiki/Filename

Мартин Фаартофт
источник
1
Я могу создать файл с именем "CLOCK $" просто отлично. Windows 7.
rory.ap
7

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

ConroyP
источник
6

Вопрос в том, пытаетесь ли вы определить, является ли имя пути допустимым путем окон или оно разрешено в системе, где выполняется код. ? Я думаю, что последнее более важно, поэтому лично я, вероятно, разложил бы полный путь и попытался бы использовать _mkdir для создания каталога, к которому принадлежит файл, а затем попытаться создать файл.

Таким образом, вы знаете не только, содержит ли путь только допустимые символы Windows, но и действительно ли он представляет путь, который может быть записан этим процессом.

КФХ
источник
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);
}
JoelFan
источник
5

Также CON, PRN, AUX, NUL, COM # и некоторые другие никогда не являются допустимыми именами файлов в любом каталоге с любым расширением.


источник
1
Это только половина правды. Вы можете создавать файлы с этими именами, если вызываете Unicode-версию CreateFile (с префиксом имени файла «\\? \»).
Вернер Хенце
Это утверждение является неполным и пропускает LPT #
Томас Веллер
4

Чтобы дополнить другие ответы, вот пара дополнительных крайних случаев, которые вы можете рассмотреть.

  • В Excel могут возникнуть проблемы, если вы сохраните книгу в файл, имя которого содержит символы «[» или «]». См. Http://support.microsoft.com/kb/215205 для получения подробной информации.

  • Sharepoint имеет целый дополнительный набор ограничений. См. Http://support.microsoft.com/kb/905231 для получения подробной информации.

Джо
источник
3

Из MSDN , вот список символов, которые не допускаются:

Используйте почти любой символ в текущей кодовой странице для имени, включая символы Юникода и символы в расширенном наборе символов (128–255), за исключением следующего:

  • Следующие зарезервированные символы недопустимы: <>: "/ \ |? *
  • Символы, чьи целочисленные представления находятся в диапазоне от нуля до 31, не допускаются.
  • Любой другой символ, который целевая файловая система не позволяет.
Марк Бик
источник
2

Также важна файловая система назначения.

Под NTFS некоторые файлы не могут быть созданы в определенных каталогах. EG $ загрузка в корне

Доминик Вебер
источник
2
Конечно, это не из-за правила именования NTFS, а просто потому, что файл с именем $Bootуже существует в каталоге?
Кристиан Хейтер
2

Это вопрос, на который уже дан ответ, но просто ради «других вариантов», вот неидеальный:

(неидеально, потому что использование исключений в качестве управления потоком, как правило, является «плохой вещью»)

public static bool IsLegalFilename(string name)
{
    try 
    {
        var fileInfo = new FileInfo(name);
        return true;
    }
    catch
    {
        return false;
    }
}
JerKimball
источник
Ваш пример не работает для файла CON (C: \ temp \ CON).
Январь
Но разве C: \ temp \ CON не является допустимым именем файла? Почему бы не быть?
Марк А. Донохо,
@MarqueIV - нет, это недействительно. Прочитайте все ответы и комментарии выше или попробуйте сами и посмотрите.
rory.ap
@Jer, "/ пример" недопустим, но ваш метод возвращает true.
rory.ap
Ааааа ... Я пропустил часть "CON". Само имя является допустимым с точки зрения строки (именно это я и имел в виду), но теперь я вижу, что CON является зарезервированным именем, что делает его недействительным с точки зрения Windows. Виноват.
Марк А. Донохо
2

Регулярные выражения излишни для этой ситуации. Вы можете использовать String.IndexOfAny()метод в сочетании с Path.GetInvalidPathChars()и Path.GetInvalidFileNameChars().

Также обратите внимание, что оба Path.GetInvalidXXX()метода клонируют внутренний массив и возвращают клон. Поэтому, если вы собираетесь делать это много раз (тысячи и тысячи раз), вы можете кэшировать копию недопустимого массива chars для повторного использования.

nhahtdh
источник
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;

Я попытался запустить этот и другие методы, упомянутые выше, для имени файла / пути 1 000 000 раз в LinqPad.

Использование Split()составляет всего ~ 850 мс.

Использование Regex("[" + Regex.Escape(new string(System.IO.Path.GetInvalidPathChars())) + "]")составляет около 6 секунд.

Более сложные регулярные выражения справляются НАМНОГО хуже, как и некоторые другие опции, такие как использование различных методов Pathкласса для получения имени файла и выполнения их внутренней проверки (скорее всего из-за накладных расходов на обработку исключений).

Конечно, не очень часто нужно проверять 1 миллион имен файлов, так что в любом случае для большинства этих методов подходит одна итерация. Но это все еще довольно эффективно и эффективно, если вы ищете только недопустимые символы.

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

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

Maxence
источник
0

Я предлагаю просто использовать Path.GetFullPath ()

string tagetFileFullNameToBeChecked;
try
{
  Path.GetFullPath(tagetFileFullNameToBeChecked)
}
catch(AugumentException ex)
{
  // invalid chars found
}
Тони Сан
источник
Добавьте некоторое объяснение с ответом о том, как этот ответ помогает ОП в исправлении текущей проблемы
ρяσѕρєя K
Посмотрите документ в MSDN для AugumentExcpetion, он читает: путь - строка нулевой длины, содержит только пробел или содержит один или несколько недопустимых символов, определенных в GetInvalidPathChars. -ИЛИ- Системе не удалось получить абсолютный путь.
Тони Сан
Теоретически (согласно документации) это должно работать, но проблема, по крайней мере, в .NET Core 3.1, не работает.
Мишель Янссон
0

Я получил эту идею от кого-то. - не знаю кто. Пусть ОС сделает тяжелую работу.

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;
}
KenR
источник
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. (Создание файла с начальными пробелами успешно в моей системе).


Используется .NET Framework 4.7.1, протестировано на Windows 7.

Влад
источник
0

Один лайнер для проверки нелегальных символов в строке:

public static bool IsValidFilename(string testName) => !Regex.IsMatch(testName, "[" + Regex.Escape(new string(System.IO.Path.InvalidPathChars)) + "]");
Zananok
источник
0

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

Игорь Левицкий
источник
-1

Имена файлов Windows , довольно unrestrictive, поэтому на самом деле это не может быть даже , что большая часть проблемы. Символы, которые запрещены Windows:

\ / : * ? " < > |

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

Джастин Поли
источник
Также символы <= 31 запрещены.
Сурьма