2012-03-13 2 views
2

Возможно, я потратил около 500 часов на поиск Google и чтение документации MSDN, и он по-прежнему отказывается работать так, как я хочу.Сортировка FileSystemInfo [] по имени

можно сортировать по имени файлов, как это:

01.png 
02.png 
03.png 
04.png 

Т.е. все-таки длина файла.

Во-вторых, есть файл с более длинной длиной файла, все идет в ад.

Например, в следующей последовательности:

1.png 
2.png 
3.png 
4.png 
5.png 
10.png 
11.png 

Он гласит:

1.png, 2.png then 10.png, 11.png 

Я не хочу этого.

Мой код:

DirectoryInfo di = new DirectoryInfo(directoryLoc); 
FileSystemInfo[] files = di.GetFileSystemInfos("*." + fileExtension); 
Array.Sort<FileSystemInfo>(files, new Comparison<FileSystemInfo>(compareFiles)); 

foreach (FileInfo fri in files) 
{ 
    fri.MoveTo(directoryLoc + "\\" + prefix + "{" + operationNumber.ToString() + "}" + (i - 1).ToString("D10") + 
     "." + fileExtension); 

    i--; 
    x++; 
    progressPB.Value = (x/fileCount) * 100; 
} 

// compare by file name 
int compareFiles(FileSystemInfo a, FileSystemInfo b) 
{ 
    // return a.LastWriteTime.CompareTo(b.LastWriteTime); 
    return a.Name.CompareTo(b.Name); 
} 
+0

Возможно ли в вашем сценарии изменить шаблон имени файла? НАПРИМЕР. от 1.png до 01.png? –

+1

Попробуйте http://stackoverflow.com/questions/1601834/c-implementation-of-or-alternative-to-strcmplogicalw-in-shlwapi-dll, 'StrCmpLogicalW' - это Windows API, который выполняет« волшебство »сортировки имена файлов «логичным» способом. – xanatos

ответ

3

Это не вопрос длины файла частности - это вопрос названия сравниваемых в лексикографическом порядке.

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

Конечно, это не сработает, если у вас есть «debug1.png, debug2.png, ... debug10.png» ... вам понадобится более сложный алгоритм в этом случае.

0

Ваш код верен и работает как ожидалось, просто сортировка выполняется в алфавитном порядке, а не в цифровом виде.

Например, строки «1», «10», «2» указаны в алфавитном порядке. Вместо этого, если вы знаете, что ваши имена файлов - это всего лишь число плюс «.png», вы можете сделать сортировку численно. Например, что-то вроде этого:

int compareFiles(FileSystemInfo a, FileSystemInfo b)   
{    
    // Given an input 10.png, parses the filename as integer to return 10 
    int first = int.Parse(Path.GetFileNameWithoutExtension(a.Name)); 
    int second = int.Parse(Path.GetFileNameWithoutExtension(b.Name)); 

    // Performs the comparison on the integer part of the filename 
    return first.CompareTo(second); 
} 
3

Вы сравнивая имена, как строк, хотя (я предполагаю), вы хотите, чтобы они отсортированы по номеру.

Это хорошо известная проблема, где «10» идет перед «9», так как первый символ в 10 (1) меньше первого символа 9.

Если вы знаете, что файлы будут все состоят из пронумерованных имен, вы можете изменить свою обычную процедуру сортировки, чтобы преобразовать имена в целые числа и отсортировать их соответствующим образом.

0

Я столкнулся с этой же проблемой, но вместо сортировки списка я изменил имя файла, используя 6-значный «0» проложенный ключ.

Мой список теперь выглядит следующим образом:

000001.jpg 
000002.jpg 
000003.jpg 
... 
000010.jpg 

Но, если вы не можете изменить имена файлов, вы будете иметь, чтобы реализовать свою собственную процедуру сортировки, чтобы иметь дело с альфа рода.

0

Как насчет немного linq и регулярного выражения, чтобы исправить порядок?

var orderedFileSysInfos = 
    new DirectoryInfo(directoryloc) 
    .GetFileSystemInfos("*." + fileExtension) 
    //regex below grabs the first bunch of consecutive digits in file name 
    //you might want something different 
    .Select(fsi => new{fsi, match = Regex.Match(fsi.Name, @"\d+")}) 
    //filter away names without digits 
    .Where(x => x.match.Success) 
    //parse the digits to int 
    .Select(x => new {x.fsi, order = int.Parse(x.match.Value)}) 
    //use this value to perform ordering 
    .OrderBy(x => x.order) 
    //select original FileSystemInfo 
    .Select(x => x.fsi) 
    //.ToArray() //maybe?