Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Упорядочивание файлов по дате их создания [D6, Win95/98]


Dr. Genius ©   (2004-12-24 15:56:00) 

В переменной FileList типа TStrings хранятся имена файлов (полные пути к файлам). Необходимо упорядочить эти имена файлов по дате их создания, и уже в упорядоченном виде произвести запись содержимого переменной FileList в текстовый файл методом SaveToFile. Проблема состоит только в том, КАК упорядочить эти файлы. Может, есть какой-то метод, позволяющий записывать имена файлов в TStrings в УЖЕ упорядоченном виде? Если да, то как это сделать?


Anatoly Podgoretsky   (2004-12-31 10:17:00) [1]

И вставил конечно с ошибками, а конкретную ошибку тебе уже указали, ты исправил уже?
Ты чего такой неправильный ник выбрал.


Dr. Genius   (2004-12-31 09:21:00) [2]

Я проверял не весь код, а взял оттуда кусок и втавил в программу...


begin...end   (2004-12-30 12:26:00) [3]

> [12] Dr. Genius   (27.12.04 10:20)

> При работе напрямую с лементами как показано в [8] Delphi
> выводит ошибку.


> [17] Dr. Genius   (30.12.04 09:21)

> Ошибка: “List index out of bounds (n)”

Т.е. Вы со всей ответственностью заявляете, что код [8] вызывает эту ошибку?


Dr. Genius   (2004-12-30 09:21:00) [4]


> Его Сиятельство таки сподобится по случаю Рождества описать
> проблему кратко, внятно, наглядно ?


Ты, наверное, разозлился из-за того, что я сказал про ошибку, но не сказал в чём она заключается. Просто я забыл текст ошибки. Я запустил Delphi и посмотрел...
Ошибка: “List index out of bounds (n)”, где n – это количество найденных графических файлов в указанной папке.
______________________________

Спасибо за код, Arm79. Теперь я понял, как отсортировывать по дате создания. Вот как я это сделал:

FileList.AddObject (Dir + Rec.Name, Pointer (Rec.FindData.ftCreationTime.dwLowDateTime));


Dr. Genius   (2004-12-28 10:19:00) [5]


> Его Сиятельство таки сподобится по случаю Рождества описать
> проблему кратко, внятно, наглядно ?


Да, но не сейчас. Попозже...


Arm79   (2004-12-27 16:58:00) [6]

Забыл добавить, список отсортированный. Поэтому я с сортировкой не мучаюсь, само вставляется куда нужно


Arm79   (2004-12-27 16:55:00) [7]

У меня процедурка собирает список файлов, правда по времени модификации, а не создания, но это несложно исправить. Нужно посмотеть в хелп по TSearchRec

procedure ReturnSnapList(var SL : TStringList);
var
 sTemp1    : string;
 FileAttrs : Integer;
 SR        : TSearchRec;
begin
 SetCurrentDir(ExtractFilePath(Application.ExeName));
 sTemp1 := GetCurrentDir + '\SnapShots\';
 FileAttrs := faAnyFile;
 if FindFirst(sTemp1 + 'SnapShot*.snp', FileAttrs, sr) = 0
   then begin
SL.AddObject(IntToStr(sr.FindData.ftLastWriteTime.dwLowDateTime), TObject(StringToPChar(sr.Name)));
     while findNext(sr) = 0
       do SL.AddObject(IntToStr(sr.FindData.ftLastWriteTime.dwLowDateTime), TObject(StringToPChar(sr.Name)));
     FindClose(sr);
   end;
 SetCurrentDir(ExtractFilePath(Application.ExeName));
end;


Digitman   (2004-12-27 11:33:00) [8]


> Delphi выводит ошибку


Рождество ? Волшебство ?
Его Сиятельство таки сподобится по случаю Рождества описать проблему кратко, внятно, наглядно ?


Dr. Genius   (2004-12-27 10:20:00) [9]


> И зачем сохранять FileList в файл? Разве нельзя работать
> с элементами списка напрямую

При работе напрямую с лементами как показано в [8] Delphi выводит ошибку.


begin...end   (2004-12-26 11:29:00) [10]

> [10] Dr. Genius   (26.12.04 11:15)

> for I := 1 to FileList.Count do        

for I := 0 to FileList.Count - 1 do

И зачем сохранять FileList в файл? Разве нельзя работать с элементами списка напрямую - так, как я это показал в [8]? Впрочем, воля Ваша...


Dr. Genius   (2004-12-26 11:15:00) [11]

Код работает, я его просмотрел. Функция MyCompareFunction выполняет сортировку по возрастанию даты изменения. В принципе, всё понятно и вопросов у меня не возникло. Выходит, что в Rec.Time хранится не дата создания файла, а дата его изменения. Получается, что через Rec нельзя организовать сортировку по дате создания (зато можно ещё по размеру файла, через Rec.Size). Ладно, значит, буду искать другой способ. Наверное, придётся прибегнуть к FileAge… Выкладываю код своей программы на всякий случай (может, кто-то захочет помочь):

program organize;
uses
 SysUtils, Classes, FileCtrl, Windows, Controls, Math;
 //----------------------------------------
 function MyCompareFunction (List: TStringList; Index1, Index2: Integer): Integer;
 begin
   Result := CompareValue (Integer (List.Objects [Index1]), Integer (List.Objects [Index2]));
 end;
 //----------------------------------------
var
 OutDir, Dir, FileName: String;
 Rec: TSearchRec;
 FileList: TStringList;
 I: Integer;
 F: TextFile;
label
 Point;
begin
 Point: if (SelectDirectory ('Выберите папку, содержащую графические файлы:', '', OutDir)) then
   begin
     FileList := TStringList.Create;
     OutDir := IncludeTrailingPathDelimiter (OutDir);
     Dir := OutDir;
     OutDir := OutDir + '*.*';
     I := FindFirst (OutDir, faAnyFile, Rec);
     while (True) do
       begin
         if (I <> 0) then Break;
         if (FileExists (Dir + Rec.Name))
           and ((ExtractFileExt (Dir + Rec.Name) = '.jpg')
           or (ExtractFileExt (Dir + Rec.Name) = '.jpe')
           or (ExtractFileExt (Dir + Rec.Name) = '.jpeg')
           or (ExtractFileExt (Dir + Rec.Name) = '.png')
           or (ExtractFileExt (Dir + Rec.Name) = '.gif')
           or (ExtractFileExt (Dir + Rec.Name) = '.bmp')
           or (ExtractFileExt (Dir + Rec.Name) = '.pcx')
           or (ExtractFileExt (Dir + Rec.Name) = '.dcx')
           or (ExtractFileExt (Dir + Rec.Name) = '.dcx')
           or (ExtractFileExt (Dir + Rec.Name) = '.tif')
           or (ExtractFileExt (Dir + Rec.Name) = '.tiff'))
         then FileList.AddObject (Dir + Rec.Name, Pointer (Rec.Time));
         I := FindNext (Rec);
       end;
     SysUtils.FindClose (Rec);
     if (FileList.Capacity = 0) then
       begin
         MessageBox (0, 'В выбранной папке не найдено ни одного графического файла.', 'Gallery Organizer 1.0', MB_OK or MB_ICONWARNING);
         goto Point;
       end;
     if (MessageBox (0, 'Вы действительно хотите сорганизовать графические файлы выбранной папки?', 'Gallery Organizer 1.0', MB_YESNO or MB_ICONQUESTION) = mrNo) then goto Point;
     FileList.CustomSort (MyCompareFunction);
     FileList.SaveToFile ('Files.tmp');
     AssignFile (F, 'Files.tmp');
     Reset (F);
     for I := 1 to FileList.Count do
       begin
         Readln (F, OutDir);
         FileName := IntToStr (I);
         while (Length (FileName) < Length (IntToStr (FileList.Count))) do FileName := '0' + FileName;
         RenameFile (OutDir, Dir + FileName + ExtractFileExt (OutDir));
       end;
     CloseFile (F);
     Erase (F);
     MessageBox (0, PChar ('Организация файлов завершена. Сорганизовано файлов: ' + IntToStr (FileList.Count) + '.'), 'Gallery Organizer 1.0', MB_OK or MB_ICONINFORMATION);
     FileList.Free;
   end;
end.


Dr. Genius   (2004-12-25 14:14:00) [12]

begin...end, спасибо за код. Сейчас буду его изучать.


begin...end   (2004-12-25 11:35:00) [13]

> [7] Dr. Genius   (25.12.04 08:53)

Писал я огромный пост, но по глупости потерял его перед самой отправкой. Так что - короткий вариант. Вот код, который переименовывает файлы на основании даты их последнего изменения. Разберитесь вначале сами. Если что-то будет совсем непонятно, задавайте вопросы.

program Sort;

uses
 SysUtils, Classes, FileCtrl, Math;

function MyCompareFunction(List: TStringList; Index1, Index2: Integer): Integer;
begin
 Result := CompareValue(Integer(List.Objects[Index1]), Integer(List.Objects[Index2]))
end;

var
 I: Integer;
 OutDir: String;
 Rec: TSearchRec;
 FileList: TStringList;
begin
 if (SelectDirectory('Выберите папку, содержащую файлы:', '', OutDir)) then
 begin
   FileList := TStringList.Create;
   try
     OutDir := IncludeTrailingPathDelimiter(OutDir);
     if FindFirst(OutDir + '*.*', faAnyFile, Rec) = 0 then
       repeat
         if (Rec.Attr and faDirectory) <> faDirectory then
           FileList.AddObject(OutDir + Rec.Name, Pointer(Rec.Time))
       until FindNext(Rec) <> 0;
     FindClose(Rec);
     FileList.CustomSort(MyCompareFunction);
     for I := 0 to FileList.Count - 1 do
       RenameFile(FileList[I], ExtractFilePath(FileList[I]) + IntToStr(I) + ExtractFileExt(FileList[I]));
   finally
     FileList.Free
   end
 end
end.


Dr. Genius   (2004-12-25 08:53:00) [14]

Привожу уже немного доработанный код программы. Теперь программа переименовывает файлы, только не графические, а все подряд; и переименовывает не по дате создания. Я всё сделал, как мне сказал Digitman, но на CustomSort я застрял. Может, кто поможет?

program imgsort;
uses
 SysUtils, Classes, FileCtrl, Windows;
var
 OutDir, TempOut, S, T: String;
 Rec: TSearchRec;
 FileList: TStringList;
 I: Integer;
 F: TextFile;
begin
 if (SelectDirectory ('Выберите папку, содержащую графические файлы:', '', OutDir)) then
   begin
     FileList := TStringList.Create;
     TempOut := OutDir + '\';
     OutDir := OutDir + '\*.*';
     I := FindFirst (OutDir, faAnyFile, Rec);
     while (True) do
       begin
         if (I <> 0) then Break;
         if (FileExists (TempOut + Rec.Name)) then FileList.AddObject (TempOut + Rec.Name, Pointer (Rec.Time));
         I := FindNext (Rec);
       end;
      //FileList.CustomSort();      SysUtils.FindClose (Rec);
     FileList.SaveToFile ('Images.tmp');
     AssignFile (F, 'Images.tmp');
     Reset (F);
     for I := 1 to FileList.Count do
       begin
         Readln (F, OutDir);
         S := OutDir;
         Delete (S, 1, Length (OutDir) - 4);
         T := IntToStr (I);
         while (Length (T) < Length (IntToStr (FileList.Count))) do T := '0' + T;
         RenameFile (OutDir, TempOut + T + S);
       end;
     CloseFile (F);
     Erase (F);
     FileList.Free;
   end;
end.


Digitman   (2004-12-24 17:18:00) [15]


> Как всё запутано и непонятно


что "запутано" и что конкретно непонятно ?


> столкнулся с ещё одной проблемой


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

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


Dr. Genius   (2004-12-24 17:07:00) [16]

Как всё запутано и непонятно. Нельзя ли привести кусок программного кода. Дело в том, что я сейчас собирался написать небольшую программку, позволяющую удобно организовывать галереи графических файлов. Например, у Вас есть папка Gallery, в ней хранится, скажем, 100 графических файлов с разными именами. Так вот: с помощью моей программы пользователь сможет за пару кликов сорганизовать все графические файлы (упорядочить, переименовывать) по дате создания. И после этого у пользователя в папке Gallery будет вот такой список файлов: 001.jpg, 002.jpg, 003.jpg, 004.jpg, … 100.jpg. Или такой: Image_001.jpg, Image_002.jpg, Image_003.jpg, Image_004.jpg, … Image_100.jpg.  Причём эти файлы будут сорганизованы по дате их создания (первым в папке будет самый старый файл, а последним – самый новый).

Привожу кусок моего, пока ещё очень скромного и недоделанного программного кода:

program imgsort;
uses
 SysUtils, Classes, FileCtrl, Windows;
var
 OutDir, TempOut: String;
 FFRec: TSearchRec;
 FileList: TStrings;
 I: Integer;
begin
 if (SelectDirectory ('Выберите папку, содержащую графические файлы:', '', OutDir)) then
   begin
     FileList := TStringList.Create;
     TempOut := OutDir + '\';
     OutDir := OutDir + '\*.*';
     I := FindFirst (OutDir, faAnyFile, FFRec);
     while (True) do
       begin
         if (I <> 0) then Break;
         if (FileExists (TempOut + FFRec.Name)) then FileList.Add (TempOut + FFRec.Name);
         I := FindNext (FFRec);
       end;
     SysUtils.FindClose (FFRec);
     FileList.SaveToFile ('Images.tmp');
     FileList.Free;
     DeleteFile ('Images.tmp');
   end;
end.


На строчке программного кода, помеченной жирным шрифтом, я столкнулся с ещё одной проблемой: '\*.*' – это критерий поиска файлов. Может, это будет смешно, но у меня не получается сделать так, чтобы вёлся поиск только файлов графического типа: *.jpg, *.gif, *.bmp, *.tif, *.pcx и т. д.


Digitman   (2004-12-24 16:15:00) [17]


> В переменной FileList типа TStrings хранятся имена файлов


они там откуда взялись ?
ты же, наверно, пользовал FindFirst/FindNext для заполнения списка ? нужно было сразу при нахождении очередного файла запоминать знач-е поля Time структуры SearchRec .. а так тебе придется для каждого файла из полученного списка запрашивать это значение, например, ф-цией FileAge() .. двойная работа, заметно снижающая производительность алгоритма в целом, из-за двойного открытия/закрытия каждого из файлов ..

когда ты получил инф-цию об очередном файле, добавляй ее в StringList методом AddObject('имя_файла', Pointer(время_создания_из_поля_SearchRec.Time))

как только стринг-лист будет заполнен, вызови его метод CustomSort() (см.справку), указав параметром адрес собственной ф-ции с прототипом TStringListSortCompare .. эта ф-ция в ходе сортировки будет вызываться многократно, в ней ты должен сравнить DWord(List.Objects[Index1]) и DWord(List.Objects[Index2]) на предмет больше/меньше/равно, вернув соответственно 1/0/-1


Александр Иванов   (2004-12-24 16:13:00) [18]

type TListSortCompare = function (Item1, Item2: Pointer): Integer;
procedure Sort(Compare: TListSortCompare);

У него просто организовать сортировку по любым критериям определив собственную ф-ю и передав ее в метод Sort.


Dr. Genius   (2004-12-24 16:10:00) [19]


> Используй TList


Поподробнее, пожалуйста...


Александр Иванов   (2004-12-24 16:05:00) [20]

Используй TList


Наверх

Титульная страница Поиск, карта сайта Написать письмо