Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Вопросы по Delphi (до версии 2009) - часть 6

Модерирует : ShIvADeSt

 Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125

Открыть новую тему     Написать ответ в эту тему

ShIvADeSt



Moderator
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Продолжение темы Вопросы по Delphi (до версии 2009) - часть 5

Познаем сами, помогаем другим...
Обсуждаем вопросы, не связанные с юникоидными версиями Delphi - для этого есть соответствующая тема (см. ссылки ниже).


 
Правила топика:
    Прежде чем спрашивать:
  1. Желательно изучить вопрос, попытаться найти ответ в прилагаемых мануалах, хелпах и анализируя исходники.
  2. Выполнить поиск по топику (открыть "Версия для печати" и поискать ответ там).
  3. Применить фильтр по разделу "Прикладное программирование". Ответы на многие старые вопросы могли быть даны в отдельных темах.
  4. Продумайте вопрос. На поверхностные вопросы вы получите поверхностные ответы, или вообще ответов не получите.
  5. Желательно указывать версии используемого компилятора и операционной системы.
    Прежде чем отвечать:
  1. Если не можете помочь, не мешайте.
  2. Если уж вы отвечаете на вопрос, давайте ответ по сути.
  3. Если вы не уверены, так и говорите! Ошибочный, но авторитетно звучащий ответ хуже, чем отсутствие ответа.
  4. Задавайте дополнительные вопросы, чтобы получить больше информации.
  • Отсутствие ответа не равносильно игнорированию - иногда участники форума просто не знают ответ. Повторная посылка вопроса не приветствуется. Посты типа "неужели никто не знает ответа..." или "может мне все-таки кто-нибудь ответит" недопустимы.  
  • Все большие куски кода (более 5 строк) оформляем в тег [morе] дабы уменьшить размер поста. FAQ по тегу [morе].


    Некоторые "родственные" топики:
     
  • Вопросы по Delphi (версии 2009-2010 Weaver)
  • Вопросы по компонентам для Delphi, C++ Builder
  • Использование DevExpress
  • Вопросы по Ehlib
  • Компоненты и утилиты для Delphi/BCB/FreePascal/Lazarus - только Open Source
  • Коммерческие компоненты и утилиты для Delphi/BCB
  • кабак программистов :)
     
    См. также: Некоторые полезные ресурсы о Delphi
     
    И старайтесь, чтобы ваш код не попал сюда :)

  • Всего записей: 3956 | Зарегистр. 29-07-2003 | Отправлено: 05:13 19-05-2010 | Исправлено: akaGM, 02:33 15-07-2020
    GRom V

    Full Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору

    Цитата:
    Сразу скажу - делать так, идея в корне неверная. После переименования сбивается список файлов, в итоге получишь ерунду.
    Правильно - вначале получаешь список файлов/каталогов с помощью рекурсии, потом пробегаешься по списку и переименовываешь.  
     

    Спасибо за помощь, если есть время, не мог бы показать как это осуществить в данной функции? Был бы при много благодарен!

    Всего записей: 466 | Зарегистр. 31-10-2006 | Отправлено: 03:19 17-01-2018
    GRom V

    Full Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    Почему то
    MoveFile(PChar(StartDir + SearchRec.Name), '0.9.21.0.3');
    и
    RenameFile(StartDir + SearchRec.Name, '0.9.21.0.3');  
    не переименовывает...

    Всего записей: 466 | Зарегистр. 31-10-2006 | Отправлено: 06:50 17-01-2018
    XenoZ



    Gold Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    Alexzzy

    Цитата:
    Делается проще. Как то так.

    Ну, изначально была задача: найти конкретную папку(папки). В этом варианте маска не нужна, а двойная рекурсиядвойной цикл - тем более.
     
    GRom V

    Цитата:
    RenameFile(StartDir + SearchRec.Name, '0.9.21.0.3');  
    не переименовывает...

    Это функция. Посмотри код ошибки и узнаешь - почему.

    ----------
    А оно мне надо?..

    Всего записей: 5438 | Зарегистр. 29-03-2006 | Отправлено: 07:33 17-01-2018 | Исправлено: XenoZ, 14:26 17-01-2018
    ShIvADeSt



    Moderator
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    GRom V

    Цитата:
    Спасибо за помощь, если есть время, не мог бы показать как это осуществить в данной функции?

    Дельфи под рукой нет, но внутри ДАННОЙ функции это сделать нельзя (неправильно).  
    Загоняете все это в TList, потом пробегаетесь по его элементам и уже им делаете Rename.
    Что то типа

    Код:
     
    for i:=0 to List.Items.Count - 1 do begin
      MyFolder := List.Items[i];
      RenameFile(MyFolder, 'new folder');
    end;
     

     
    А вообще для начала для теста попробуйте сделать так
    RenameFile(StartDir + SearchRec.Name, StartDir + '0.9.21.0.3');  
    то есть указывая полный путь и к исходной папке, и к результирующей.
    Либо вообще проверить, как корректно прописать
    RenameFile('полный путь к старой папке', 'полный путь к папке с новым именем');


    ----------
    И создал Бог женщину... Существо получилось злобное, но забавное...

    Всего записей: 3956 | Зарегистр. 29-07-2003 | Отправлено: 09:00 17-01-2018 | Исправлено: ShIvADeSt, 09:01 17-01-2018
    GRom V

    Full Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору

    Цитата:
    А вообще для начала для теста попробуйте сделать так
    RenameFile(StartDir + SearchRec.Name, StartDir + '0.9.21.0.3');  
    то есть указывая полный путь и к исходной папке, и к результирующей.  

    Да, так все работает! А почему нельзя внутри функции - ну будет находить и сразу переименовывать.?
    Так же проще?

    Всего записей: 466 | Зарегистр. 31-10-2006 | Отправлено: 09:14 17-01-2018
    ShIvADeSt



    Moderator
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    GRom V

    Цитата:
    Да, так все работает! А почему нельзя внутри функции - ну будет находить и сразу переименовывать.?  

    Будет сбиваться структура каталога, который в данный момент обходится. То есть ваш каталог был н-р 3, а может стать 7 в папке. В итоге, у Вас не будет гарантии, что программа корректно переименовала нужные файлы.
    Я так один раз влетел, долго не мог понять почему не все записи обрабатываются. А программа честно брала следующую запись, так как не знала, что порядок изменился.

    ----------
    И создал Бог женщину... Существо получилось злобное, но забавное...

    Всего записей: 3956 | Зарегистр. 29-07-2003 | Отправлено: 09:19 17-01-2018
    GRom V

    Full Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору

    Цитата:
    Будет сбиваться структура каталога, который в данный момент обходится. То есть ваш каталог был н-р 3, а может стать 7 в папке. В итоге, у Вас не будет гарантии, что программа корректно переименовала нужные файлы.
    Я так один раз влетел, долго не мог понять почему не все записи обрабатываются. А программа честно брала следующую запись, так как не знала, что порядок изменился.

    Я пробовал после:
    List.Add('DIR: ' + StartDir + SearchRec.Name + '\');
     
    ставить: showmessage(StartDir + SearchRec.Name);
    И у меня после каждой найденной папки появлялось сообщение из чего я сделал вывод что если вставить переименование - после каждой найденной папки тут же будет переименовываться.
     
    все вроде работает единственное я не могу в RenameFile(StartDir + SearchRec.Name, StartDir + '0.9.21.0.3');    вместо '0.9.21.0.3' вставит Eiit2.Text - ругается
     
    Добавлено:
    А вот это:
    for i:=0 to List.Items.Count - 1 do begin
      MyFolder := List.Items[i];
      RenameFile(MyFolder, 'new folder');
    end;  
    Можно при нажатии кнопки сделать?

    Всего записей: 466 | Зарегистр. 31-10-2006 | Отправлено: 09:29 17-01-2018
    Alexzzy

    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    XenoZ

    Цитата:
    Ну, изначально была задача: найти конкретную папку(папки). В этом варианте маска не нужна, а двойная рекурсия - тем более.

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

    Всего записей: 1474 | Зарегистр. 10-07-2013 | Отправлено: 11:16 17-01-2018
    GRom V

    Full Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    В общем сделал так:
    procedure ScanDir(StartDir, Mask, Mask2: string; List: TStrings);
    var
      SearchRec: TSearchRec;
    begin
      StartDir := IncludeTrailingPathDelimiter(StartDir);
     
      {поиск по маске в текущей директории}
      if FindFirst(StartDir + Mask, faAnyFile, SearchRec) = 0 then
      begin
        repeat
          if (SearchRec.Attr and faDirectory) = faDirectory then
          begin
            if (SearchRec.Name <> '..') and (SearchRec.Name <> '.') then begin
              List.Add('DIR: ' + StartDir + SearchRec.Name + '\');
              //////////////////////////////////////////////////////////////////////////
              RenameFile(StartDir + SearchRec.Name, StartDir + Mask2);
          end;
          end
          else
            List.Add('FILE: ' + StartDir + SearchRec.Name);
        until FindNext(SearchRec) <> 0;
        FindClose(SearchRec);
      end;
     
      {рекурсивный обход всех поддиректорий}
      if FindFirst(StartDir + '*', faDirectory, SearchRec) = 0 then
      begin
        repeat
          if (SearchRec.Name <> '..') and (SearchRec.Name <> '.') then
            ScanDir(StartDir + SearchRec.Name, Mask, Mask2, List);
        until FindNext(SearchRec) <> 0;
        FindClose(SearchRec);
      end;
          end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      ListBox1.Items.Clear;
      ScanDir(Label2.Caption, Edit1.Text, Edit2.Text, ListBox1.Items);
      Label1.Caption := 'Найдено' + ' ' + IntToStr(ListBox1.Items.Count);
      ScanDir(Label2.Caption, Edit2.Text, '', ListBox2.Items);
      Label3.Caption := 'переименовано' + ' ' + IntToStr(ListBox2.Items.Count);
    end;
     
     
    procedure TForm1.Button2Click(Sender: TObject);
    var
      chosenDirectory : string;
    begin
      if SelectDirectory('Выберите каталог', '', chosenDirectory)
      then
      Label2.Caption:= chosenDirectory
      else ShowMessage('Выбор каталога прервался');
    end;
     
    Вроде работает, и во втором листе видно результат... Так пойдет?

    Всего записей: 466 | Зарегистр. 31-10-2006 | Отправлено: 14:20 17-01-2018 | Исправлено: GRom V, 14:21 17-01-2018
    XenoZ



    Gold Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    Alexzzy

    Цитата:
    Что-то я двойной рекурсии нигде не заметил.

    Пардон, не то ляпнул спросонья. Исправился.
    Имел в виду двойной цикл, конечно. Твой вариант, в принципе, универсален, но для данной задачи он избыточен.
     
    ShIvADeSt

    Цитата:
    Дельфи под рукой нет, но внутри ДАННОЙ функции это сделать нельзя (неправильно).

    Ммм... В свое время писал программку с обработкой/переименованием файлов именно внутри, никаких проблем не заметил.
     

    Цитата:
    Либо вообще проверить, как корректно прописать
    RenameFile('полный путь к старой папке', 'полный путь к папке с новым именем');

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

    ----------
    А оно мне надо?..

    Всего записей: 5438 | Зарегистр. 29-03-2006 | Отправлено: 14:41 17-01-2018
    ShIvADeSt



    Moderator
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    XenoZ

    Цитата:
    В свое время писал программку с обработкой/переименованием файлов именно внутри, никаких проблем не заметил.

    Ну мое предположение проверить легко.
    Сделайте 10 файлов с именами
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    запустите рекурсию с переименованием путем дописывания 1 вначале имени. По идее должно будет получиться так
    11
    12
    ...
    110
    В реальности получится немного другая картина. Останется ряд файлов со старыми именами, и будет несколько файлов с несколькими 1 вначале.

    ----------
    И создал Бог женщину... Существо получилось злобное, но забавное...

    Всего записей: 3956 | Зарегистр. 29-07-2003 | Отправлено: 04:11 18-01-2018
    XenoZ



    Gold Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    ShIvADeSt

    Цитата:
    Ну мое предположение проверить легко.

    Проверил... Наглядно!
    Таки да, поиском нужно только формировать список, а переименование - отдельным циклом.

    ----------
    А оно мне надо?..

    Всего записей: 5438 | Зарегистр. 29-03-2006 | Отправлено: 14:52 18-01-2018
    GRom V

    Full Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    И снова доброе время.
    Все таже функция:
    procedure ScanDir(StartDir, Mask, Mask2: string; List: TStrings);
    var
      SearchRec: TSearchRec;
    begin
      StartDir := IncludeTrailingPathDelimiter(StartDir);
     
      if FindFirst(StartDir + Mask, faAnyFile, SearchRec) = 0 then
      begin
        repeat
          if (SearchRec.Attr and faDirectory) = faDirectory then
          begin
            if (SearchRec.Name <> '..') and (SearchRec.Name <> '.') then begin
              //List.Add('DIR: ' + StartDir + SearchRec.Name + '\');
              List.Add('' + StartDir + SearchRec.Name + '\');
              //////////////////////////////////////////////////////////////////////////
              RenameFile(StartDir + SearchRec.Name, StartDir + Mask2);
          end;
          end
          else
            //List.Add('FILE: ' + StartDir + SearchRec.Name);
            List.Add('' + StartDir + SearchRec.Name);
            RenameFile(StartDir + SearchRec.Name, StartDir + Mask2);
        until FindNext(SearchRec) <> 0;
        FindClose(SearchRec);
      end;
     
      if FindFirst(StartDir + '*', faDirectory, SearchRec) = 0 then
      begin
        repeat
          if (SearchRec.Name <> '..') and (SearchRec.Name <> '.') then
            ScanDir(StartDir + SearchRec.Name, Mask, Mask2, List);
        until FindNext(SearchRec) <> 0;
        FindClose(SearchRec);
      end;
          end;
     
    Есть один недостаток - в листбокс строки появляются только когда сканирование завершено а во время выполнения как будто висяк. Как сделать чтоб строка с найденным файлом, при сканировании, появлялась сразу?

    Всего записей: 466 | Зарегистр. 31-10-2006 | Отправлено: 14:41 19-01-2018
    XenoZ



    Gold Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    GRom V

    Цитата:
    во время выполнения как будто висяк.

    Application.ProcessMessages;

    ----------
    А оно мне надо?..

    Всего записей: 5438 | Зарегистр. 29-03-2006 | Отправлено: 16:03 19-01-2018
    Frodo_Torbins

    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    XenoZ
    Только тогда всем формам Enable := False надо делать, а то можно еще что-нибудь запустить до окончания поиска.

    Всего записей: 2318 | Зарегистр. 24-05-2007 | Отправлено: 17:25 19-01-2018
    GRom V

    Full Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору

    Цитата:
    Application.ProcessMessages;

    ее надо в начале функции вставить?
     
    Добавлено:
    Да и еще... как остановить процесс поиска?

    Всего записей: 466 | Зарегистр. 31-10-2006 | Отправлено: 18:19 19-01-2018
    XenoZ



    Gold Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    GRom V

    Цитата:
    ее надо в начале функции вставить?

    Ее надо вставить в цикл.
     

    Цитата:
    как остановить процесс поиска?

    Добавь глобальный флаг и подключи его проверку, к примеру, в until ..
    Установку флага повесь на кнопку.

    ----------
    А оно мне надо?..

    Всего записей: 5438 | Зарегистр. 29-03-2006 | Отправлено: 18:47 19-01-2018
    GRom V

    Full Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору

    Цитата:
    Ее надо вставить в цикл.  

    Прошу прощения за тупой вопрос - можно конкретно? Я ставил сюда и все вроде работает:
    procedure ScanDir(StartDir, Mask, Mask2: string; List: TStrings);
    var
      SearchRec: TSearchRec;
    begin
      StartDir := IncludeTrailingPathDelimiter(StartDir);  
      Application.ProcessMessages;  
     
     
     
    Добавлено:

    Цитата:
    Добавь глобальный флаг и подключи его проверку, к примеру, в until ..
    Установку флага повесь на кнопку.

    Можно пример остановки?

    Всего записей: 466 | Зарегистр. 31-10-2006 | Отправлено: 01:46 20-01-2018 | Исправлено: GRom V, 02:47 20-01-2018
    XenoZ



    Gold Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    GRom V

    Цитата:
    можно конкретно?

    В твоем коде два цикла repeat .. until.
     

    Цитата:
    Можно пример остановки?

    Примерно так...

    ----------
    А оно мне надо?..

    Всего записей: 5438 | Зарегистр. 29-03-2006 | Отправлено: 10:09 20-01-2018
    GRom V

    Full Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору

    Цитата:
    В твоем коде два цикла repeat .. until.  

     
    т.е. так?
     
    begin
        repeat
          Application.ProcessMessages
          if (SearchRec.Attr and faDirectory) = faDirectory then
          begin
            if (SearchRec.Name <> '..') and (SearchRec.Name <> '.') then begin
              List.Add('' + StartDir + SearchRec.Name + '\');  
             

    Всего записей: 466 | Зарегистр. 31-10-2006 | Отправлено: 12:01 20-01-2018
    Открыть новую тему     Написать ответ в эту тему

    Страницы: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125

    Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Вопросы по Delphi (до версии 2009) - часть 6


    Реклама на форуме Ru.Board.

    Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
    Modified by Ru.B0ard
    © Ru.B0ard 2000-2024

    BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

    Рейтинг.ru