Як перевірити, чи вказаний рядок є юридичним / дійсним ім'ям файлу під Windows?


165

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


Я пропоную використовувати статичний компільований Regex, якщо ви збираєтесь використовувати будь-яку відповідь з Regex ..
AMissico

Відповіді:


100

Ви можете отримати список недійсних символів із Path.GetInvalidPathCharsта GetInvalidFileNameChars.

UPD: Див . Пропозицію Стіва Купера про те, як використовувати їх у регулярному виразі.

UPD2: Зауважте, що згідно з розділом "Зауваження" в MSDN "Масив, повернутий за допомогою цього методу, не гарантується, що він містить повний набір символів, які є недійсними у назвах файлів та каталогів." Відповідь, яку надають шістьлеткових предметів, детальніше описується .


11
Це не дає відповіді на запитання; Є багато рядків, що складаються лише з дійсних символів (наприклад, "....", "CON", рядки, що мають сотні символів), які не є дійсними іменами.
Dour High Arch

31
Хтось ще розчарований, що MS не забезпечує функцію / API системного рівня для цієї можливості, а не кожен розробник повинен готувати своє власне рішення? Цікаво, чи є для цього дуже вагомі причини чи просто нагляд з боку MS.
Thomas Nguyen

@ Висока арка: див. Відповідь на запитання "У C # перевірте, чи ім'я файлу можливо допустиме (не те, що воно існує)". (Хоча деякі розумні хлопці закрили це питання на користь цього ...)
mmmmmmmm

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)

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 Я думаю, у вас є додаткова відкриваюча дужка в цьому Regex. "(^ (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

Для .Net Frameworks до 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 = новий Regex ("[" + Regex.Escape (strTheseAreInvalidFileNameChars) + "]");
rao

2
Невелике дослідження людей творить чудеса. Я оновив публікацію, щоб відобразити зміни.
Ерік Філіпс

1
2-й фрагмент коду не складається. "Неможливо перетворити з char [] в рядок
Пол Хант,

1
@AshkanMobayenKhiabani: InvalidPathChars є застарілим, але GetInvalidPathChars - ні.
ІванХ

25

Спробуйте скористатися нею і вловлюйте помилку. Дозволений набір може змінюватися в файлових системах або в різних версіях Windows. Іншими словами, якщо ви хочете дізнатися, чи подобається це ім’я Windows, передайте його ім'я та дозвольте вам сказати.


1
Це здається єдиним, хто перевіряє всі обмеження. Чому на це обираються інші відповіді?
розрив

5
@gap, оскільки це не завжди працює. Наприклад, спроба отримати доступ до 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 / ...
Навфал

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 повідомляє про помилки.
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))
}

Ви мали на увазі: "return! FileName.Any (f => Path.GetInvalidFileNameChars (). Містить (f));" ?
Джек Гріффін

@JackGriffin Звичайно! Дякую за уважність
tmt

Незважаючи на те, що цей код дуже приємно читати, ми повинні брати до уваги жалюгідні внутрішні записи Path.GetInvalidFileNameChars. Подивіться тут: referenceource.microsoft.com/#mscorlib/system/io/path.cs,289 - для кожного вашого символу fileNameстворюється клон масиву.
Пьотр Цирхоффер

"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 - Наприклад, Linux дозволяє використовувати "*: <>? \ | навіть у NTFS.

Джерело: http://en.wikipedia.org/wiki/Filename


1
Я просто можу створити файл під назвою "CLOCK $". Windows 7.
rory.ap

7

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


6

Питання полягає в тому, чи ви намагаєтеся визначити, чи ім'я контуру - законний шлях до Windows, чи законний він у системі, де працює код. ? Я думаю, що останнє важливіше, тому особисто я, мабуть, розкладу повний шлях і спробую використовувати _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);
}

5

Також CON, PRN, AUX, NUL, COM # та кілька інших ніколи не є юридичними іменами в будь-якому каталозі з будь-яким розширенням.


1
Це лише половина правди. Ви можете створити файли з цими іменами, якщо викликати версію Unicode CreateFile (префіксація імені файлу "\\? \").
Вернер Гензе

Це твердження є неповним і пропускає LPT #
Thomas Weller

4

Щоб доповнити інші відповіді, ось декілька додаткових випадків, які ви можете розглянути.

  • У програмі Excel можуть виникнути проблеми, якщо ви збережете робочу книжку у файлі, ім'я якого містить символи '[' або ']'. Докладні відомості див. У розділі http://support.microsoft.com/kb/215205 .

  • У Sharepoint є цілий додатковий набір обмежень. Докладні відомості див. У розділі http://support.microsoft.com/kb/905231 .


3

З MSDN , ось список символів, які заборонено:

Використовуйте майже будь-який символ на поточній кодовій сторінці для імені, включаючи символи Unicode та символи у розширеному наборі символів (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;
    }
}

Ваш приклад не працював для файлу CON (C: \ temp \ CON).
tcbrazil

Але чи не 'C: \ temp \ CON' дійсне ім’я файлу? Чому б цього не було?
Марк А. Донохое

@MarqueIV - ні, це не вірно. Прочитайте всі відповіді та коментарі вище, або спробуйте самі та побачите.
rory.ap

@Jer, "/ example" не є законним, але ваш метод повертається true.
rory.ap

Аааа ... я пропустив частину "CON". Саме ім'я є дійсним з точки зору рядка (про що я й мав на увазі), але я бачу, що CON - це зарезервоване ім'я, що робить його недійсним з точки зору Windows. Моє ліжко.
Марк А. Донохое

2

Регулярні вирази є надмірними для цієї ситуації. Ви можете використовувати String.IndexOfAny()метод у поєднанні з Path.GetInvalidPathChars()таPath.GetInvalidFileNameChars() .

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


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()лише ~ 850ms.

Використання 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;
  }
}

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

Ви також можете використовувати перший метод для базової перевірки, а потім уважно обробляти винятки, коли використовується шлях.


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

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)) + "]");

0

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


-1

Імена файлів Windows , досить unrestrictive, тому на самому ділі це не може бути навіть , що велика частина проблеми. Символи, які Windows забороняє:

\ / : * ? " < > |

Ви можете легко написати вираз, щоб перевірити, чи є ці символи. Хоча краще рішення буде спробувати назвати файли так, як бажає користувач, і попередити їх, коли ім'я файлу не прилипне.


Також символи <= 31 заборонені.
Сурма
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.