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


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.