Точное совпадение расширения файла с GetFiles()?

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

DirectoryInfo di = new DirectoryInfo(someValidPath);
List<FileInfo> myFiles = new List<FileInfo>();
foreach (FileInfo fi in di.GetFiles("*.txt"))
{
    myFiles.Add(fi);
}

Я получаю файлы с расширением *.txt, но я также получаю файлы с расширением *.txtx, поэтому то, что я закодировал, сводится к получению файлов, расширение которых начинается с txt.

Это не то, чего я хочу. Нужно ли мне захватить все имена файлов и выполнить регулярное выражение, соответствующее "\\.txt$" (я думаю), или проверить каждую строку имени файла с помощью .EndsWith(".txt") и т. д., чтобы выполнить это?

Спасибо!


person John    schedule 06.04.2011    source источник
comment
Да, вы делаете. Так ли это сложно и зачем нужны регулярные выражения?   -  person    schedule 07.04.2011
comment
Остерегайтесь, каждый ответ забывает, что имена файлов Windows нечувствительны к регистру. Вы также можете получить .TXT. Правила регистра для имен файлов немного неприятны, вы можете проверить длину строки.   -  person Hans Passant    schedule 07.04.2011
comment
@ Ханс: Хороший вопрос. Решает ли ответ Фредрика проблему нечувствительности к регистру?   -  person John    schedule 07.04.2011
comment
Эм, так лучше. Как я уже сказал, противно, файловая система держит свои собственные правила регистра. Код Фредрика работает, если это просто .txt   -  person Hans Passant    schedule 07.04.2011


Ответы (7)


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

foreach (FileInfo fi in di.GetFiles("*.txt")
    .Where(fi => string.Compare(".txt", fi.Extension, StringComparison.OrdinalIgnoreCase) == 0))
{
   myFiles.Add(fi);
}

Обратите внимание, что это сделает сопоставление расширения нечувствительным к регистру.

person Fredrik Mörk    schedule 06.04.2011

Использование функции списков AddRange вместо выполнения цикла foreach и вызова Add для каждого элемента, возвращаемого приведенным ниже выражением (которое я сохраняю в списке переменных).

var list = di.GetFiles("*.txt").Where(f => f.Extension == ".txt");
myFiles.AddRange(list);

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

List<FileInfo> myFiles = di.GetFiles("*.txt").Where(f => f.Extension == ".txt").ToList();
person Chuck Savage    schedule 06.04.2011
comment
Отредактировал и привел еще немного примера. - person Chuck Savage; 07.04.2011

Regex может быть излишним. Используйте расширение в FileInfo.

foreach (FileInfo fi in di.GetFiles("*.txt").Where(f => f.Extension == ".txt"))
{
     myFiles.Add(fi);
} 
person vcsjones    schedule 06.04.2011
comment
вместо цикла foreach вы можете сделать myFiles.AddRange( the expression ) - person Chuck Savage; 07.04.2011
comment
@Chuck Savage: выражение является частью цикла foreach, следующего за in? - person John; 07.04.2011

Попробуй это:

DirectoryInfo di = new DirectoryInfo(someValidPath); 
List<FileInfo> myFiles =  
    (
        from file in di.GetFiles("*.txt")
        where file.Extension == ".txt"
        select file
    ).ToList();
person Chandu    schedule 06.04.2011

Не могли бы вы просто добавить if и проверить последние четыре символа имени файла?

person MPękalski    schedule 06.04.2011

Если вы используете C# 2.0, не проще ли?

string fileExtensionFilter = "*.txt";
            DirectoryInfo di = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
            List<FileInfo> myFiles = new List<FileInfo>();
            foreach (FileInfo fi in di.GetFiles(fileExtensionFilter))
            {
                if (fi.Extension == fileExtensionFilter.Substring(1)) myFiles.Add(fi);
            }
person VictorPeralta    schedule 06.04.2011

У меня был шаблон, предоставленный пользователем, поэтому многие другие ответы меня не устраивали. Я закончил с этим более общим решением:

public string[] GetFiles(string path, string pattern)
{
    bool lastWildIsHook = false;
    if(pattern.EndsWith("?"))
    {
        pattern = pattern.Substring(0, pattern.Length - 1);
        lastWildIsHook = true;
    }
    var lastWildIndex = Math.Max(pattern.LastIndexOf("*"), pattern.LastIndexOf("?"));
    var endsWith = pattern.Length > lastWildIndex ? pattern.Substring(lastWildIndex + 1) : pattern;
    if(!lastWildIsHook)
        return Directory.GetFiles(path, pattern).Where(p => p.EndsWith(endsWith)).ToArray();
    else
        return Directory.GetFiles(path, pattern).Where(p => p.EndsWith(endsWith) || p.Substring(0, p.Length - 1).EndsWith(endsWith)).ToArray();
}
person Nick Gotch    schedule 21.11.2013