Самый простой способ проверить, является ли произвольная строка допустимым именем файла


79

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

Как это сделать проще всего?

По закону я обращаюсь к легальным и несуществующим


Когда вы говорите допустимое имя файла, вы имеете в виду тот факт, что файл существует, или вы спрашиваете, будет ли это имя разрешено операционной системой?
— Джесси МакКаллох

4
Действительно, как в (а) существующем, (б) законном или (в) законном и несуществующем?
— Энтони Пеграм

Срай, я должен был это пояснить. Он должен быть (c) leagl и несуществующим
— RoflcoptrException

4
@roflcopter: вы должны просто обрабатывать ошибки при создании файла. Любая операция файловой системы, которая включает проверку существования, уже потенциально устарела к моменту ее возврата, поскольку файловая система является глобальным общим ресурсом.
— Ben Voigt

1
@Roflcoptr: файл с тем же именем, создаваемый между моментом, когда вы проверяете действительность и / или существование, и моментом, когда вы фактически пытаетесь его создать, не следует рассматривать как нормальный поток программы. Вы должны убедиться, что файл не существует, но когда вы действительно создаете файл, эти знания уже устарели и должны рассматриваться только как обоснованное предположение. Вероятно, это все еще будет правдой, но это не гарантировано .
— Fredrik Mörk

Ответы:


125

Проверить, есть ли filename.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0и!File.Exists(Path.Combine(someFolder, filename))


1
Однако проверьте ответ Фила Ханта; похоже, что InvalidPathChars - это устаревший API, и вместо него следует использовать GetInvalidFileNameChars ().
— GendoIkari

3
<quote> Массив, возвращаемый этим методом, не гарантирует, что он будет содержать полный набор символов, недопустимых в именах файлов и каталогов. </quote> Кроме того, это свойство устарело.
— Ben Voigt

4
контрпример: "http://www.microsoft.com/"прошел тест, но имя файла недействительно, то же самое для"::::"
— Ben Voigt

3
Другие контрпримеры: "" недействителен и новая строка ('x', 1024) также недействительна.
— Расмус Фабер

2
@shellster Вы можете переименовать файл в «.txt» в проводнике Windows, указав в проводнике переименовать файл в «.txt.». Просто подсказка (или ".txt ........" тоже подойдет).
— Роберт Макки

37

Проверить против GetInvalidFileNameChars():

var isValid = !string.IsNullOrEmpty(fileName) &&
              fileName.IndexOfAny(Path.GetInvalidFileNameChars()) < 0 &&
              !File.Exists(Path.Combine(sourceFolder, fileName));

2
контрпример: "http://www.microsoft.com/"прошел тест, но имя файла недействительно, то же самое для"::::"
— Бен Фойгт

1
@Ben Voigt: Вы правы, что ::::ошибочно считалось действительным. Я исправил ответ, указав < 0вместо == 0.
— Фил Хант

1
О, я только что заметил, что вы используете GetInvalidFileNameChars, а не GetInvalidPathCharsSLaks. Если это проверка только имени файла, а не имени файла с путем, все будет в порядке.
— Ben Voigt

@Ben Voigt: Поскольку OP спрашивал о проверке имен файлов и путей только неявно для проверки отсутствия файлов, я использовал GetInvalidFileNameChars:-)
— Фил Хант

11

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

Единственный по-настоящему надежный способ определить, приемлемо ли имя файла, - это попробовать его. Разрешения - это болото.


Диалог с файлом - отвлекающий маневр, но +1 за "единственный действительно надежный способ ... это попробовать".
— Ben Voigt

1
Согласовано. Даже если имя файла не существует и не содержит недопустимых символов, существует ряд причин, по которым файл не создается, наиболее очевидной из которых является отсутствие разрешения на создание каталога.
— Боб Кауфман,

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

2

Я использую это:

public static bool IsValidFileName(string name) {
    if(string.IsNullOrWhiteSpace(name)) return false;
    if(name.Length > 1 && name[1] == ':') {
        if(name.Length < 4 || name.ToLower()[0] < 'a' || name.ToLower()[0] > 'z' || name[2] != '\\') return false;
        name = name.Substring(3);
    }
    if(name.StartsWith("\\\\")) name = name.Substring(1);
    if(name.EndsWith("\\") || !name.Trim().Equals(name) || name.Contains("\\\\") ||
        name.IndexOfAny(Path.GetInvalidFileNameChars().Where(x=>x!='\\').ToArray()) >= 0) return false;
    return true;
}

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


0

Это просто идея. Следует заполнить список исключений:

public static bool IsValidFilename(string filename)
{
    try
    {
        File.OpenRead(filename).Close();
    }
    catch (ArgumentException) { return false; }
    catch (Exception) { }
    return true;
}

Что делать, если файл еще не существует?
— Mike Cheel

@MikeCheel Код возвращает false только в случае возникновения исключения аргумента. Это исключение возникает только в том случае, если имя файла неверно.
— Бурак,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.