Фильтрация имен файлов: получение * .abc без * .abcd или * .abcde и т. Д. - PullRequest
8 голосов
/ 13 января 2009

Directory.GetFiles (LocalFilePath, searchPattern);

MSDN Примечания:

При использовании подстановочного знака звездочки в searchPattern, такого как " .txt", поведение сопоставления, когда расширение имеет длину ровно три символа, отличается от того, когда расширение имеет длину больше или меньше трех символов. SearchPattern с расширением файла ровно из трех символов возвращает файлы с расширением из трех или более символов, где первые три символа соответствуют расширению файла, указанному в searchPattern. SearchPattern с расширением файла, состоящим из одного, двух или более трех символов, возвращает только файлы с расширениями точно такой длины, которые соответствуют расширению файла, указанному в searchPattern. При использовании подстановочного знака вопросительного знака этот метод возвращает только файлы, которые соответствуют указанному расширению файла. Например, при наличии двух файлов «file1.txt» и «file1.txtother» в каталоге шаблон поиска «file? .Txt» возвращает только первый файл, а шаблон поиска «file ». TXT "возвращает оба файла.

В следующем списке показано поведение различной длины для параметра searchPattern:

  • *.abc возвращает файлы с расширением .abc, .abcd, .abcde, .abcdef и т. Д.

  • *.abcd возвращает только файлы с расширением .abcd.

  • *.abcde возвращает только файлы с расширением .abcde.

  • *.abcdef возвращает только файлы с расширением .abcdef.

Если для параметра searchPattern установлено значение *.abc, как я могу вернуть файлы с расширением .abc, а не .abcd, .abcde и т. Д.?

Может быть, эта функция будет работать:

    private bool StriktMatch(string fileExtension, string searchPattern)
    {
        bool isStriktMatch = false;

        string extension = searchPattern.Substring(searchPattern.LastIndexOf('.'));

        if (String.IsNullOrEmpty(extension))
        {
            isStriktMatch = true;
        }
        else if (extension.IndexOfAny(new char[] { '*', '?' }) != -1)
        {
            isStriktMatch = true;
        }
        else if (String.Compare(fileExtension, extension, true) == 0)
        {
            isStriktMatch = true;
        }
        else
        {
            isStriktMatch = false;
        }

        return isStriktMatch;
    }

Тестовая программа:

class Program
{
    static void Main(string[] args)
    {
        string[] fileNames = Directory.GetFiles("C:\\document", "*.abc");

        ArrayList al = new ArrayList();

        for (int i = 0; i < fileNames.Length; i++)
        {
            FileInfo file = new FileInfo(fileNames[i]);
            if (StriktMatch(file.Extension, "*.abc"))
            {
                al.Add(fileNames[i]);
            }
        }

        fileNames = (String[])al.ToArray(typeof(String));

        foreach (string s in fileNames)
        {
            Console.WriteLine(s);
        }

        Console.Read();
    }

Кто-нибудь еще лучшее решение?

Ответы [ 5 ]

9 голосов
/ 13 января 2009

Ответ таков: необходимо выполнить пост-фильтрацию. GetFiles не может сделать это. Вот пример, который опубликует ваши результаты. При этом вы можете использовать шаблон поиска с GetFiles или нет - он будет работать в любом случае.

List<string> fileNames = new List<string>();
// populate all filenames here with a Directory.GetFiles or whatever

string srcDir = "from"; // set this
string destDir = "to"; // set this too

// this filters the names in the list to just those that end with ".doc"
foreach (var f in fileNames.All(f => f.ToLower().EndsWith(".doc")))
{
    try
    {
        File.Copy(Path.Combine(srcDir, f), Path.Combine(destDir, f));
    }
    catch { ... }
}
5 голосов
/ 13 января 2009

Не ошибка, извращенное, но хорошо документированное поведение. * .doc соответствует * .docx на основе 8.3 резервного поиска.

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

0 голосов
/ 13 января 2009

Так как для "* .abc" GetFiles будет возвращать расширения 3 или более, что угодно с длиной 3 после "." является точным соответствием, и ничего более не соответствует.

string[] fileList = Directory.GetFiles(path, "*.abc");

foreach (string file in fileList)
{
   FileInfo fInfo = new FileInfo(file);

   if (fInfo.Extension.Length == 4) // "." is counted in the length
   {
      // exact extension match - process the file...
   }
}

Не уверен в производительности вышеприведенного - хотя он использует простые сравнения длин, а не манипуляции со строками, каждый раз вызывается новый FileInfo ().

0 голосов
/ 13 января 2009

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

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=95415

0 голосов
/ 13 января 2009

используйте linq ....

    string strSomePath = "c:\\SomeFolder";
string strSomePattern = "*.abc";
string[] filez = Directory.GetFiles(strSomePath, strSomePattern);

var filtrd = from f in filez
         where f.EndsWith( strSomePattern )
         select f;

foreach (string strSomeFileName in filtrd)
{
    Console.WriteLine( strSomeFileName );
}
...