Логин:     Забыли пароль?
 
Пароль:   Регистрация

Форум / Программирование - Поиск файлов. Ахтунг!!!  

Поиск файлов. Ахтунг!!!


Страницы: «1» «2»
DNK
DNK
Студент
Сообщения: 242
[Сообщение #1] 29 февраля 2012, 14:14
Недавно на своем живом опыте убедился, что не надо верить всему, что пишут в книжках. В справке к Delphi 7 присутствует описание примера поиска файлов

Цитата:

Delphi Object and Component Reference
FindFirst, FindNext, FindClose example
------------------------------------------------------------------------------------
The following example uses an edit control, a button, a string grid, and seven check boxes. The check boxes correspond to the seven possible file attributes. When the button is clicked, the path specified in the edit control is searched for files matching the checked file attributes. The names and sizes of the matching files are inserted into the string grid.

procedure TForm1.Button1Click(Sender: TObject);
 
var
  sr: TSearchRec;
  FileAttrs: Integer;
begin
  StringGrid1.RowCount := 1;
  if CheckBox1.Checked then
    FileAttrs := faReadOnly
  else
    FileAttrs := 0;
  if CheckBox2.Checked then
    FileAttrs := FileAttrs + faHidden;
  if CheckBox3.Checked then
    FileAttrs := FileAttrs + faSysFile;
  if CheckBox4.Checked then
    FileAttrs := FileAttrs + faVolumeID;
  if CheckBox5.Checked then
 
    FileAttrs := FileAttrs + faDirectory;
  if CheckBox6.Checked then
    FileAttrs := FileAttrs + faArchive;
  if CheckBox7.Checked then
 
    FileAttrs := FileAttrs + faAnyFile;
 
  with StringGrid1 do
  begin
    RowCount := 0;
 
    if FindFirst(Edit1.Text, FileAttrs, sr) = 0 then
 
    begin
      repeat
        if (sr.Attr and FileAttrs) = sr.Attr then
        begin
        RowCount := RowCount + 1;
        Cells[1,RowCount-1] := sr.Name;
        Cells[2,RowCount-1] := IntToStr(sr.Size);
        end;
      until FindNext(sr) <> 0;
      FindClose(sr);
    end;
  end;
end;


Началось история с того, что наши пользователи начали переходить на W7 и взяли моду работать под ограниченным пользователем. Это само собой плачевно сказывается на попытках программы сохранить какие либо данные в установочную дирректорию. Самым логичным оказалось перенаправить эту деятельность в личную директорию пользователя (c:\Users\User\AppData\Roaming\;), но меня ждал сюрпиз: все алгоритмы поиска файлов стали выдавать 0 файлов. Эти алгоритмы были написаны не мной, но в чистой классике жанра (возможно даже скопипастщины).
Как показал дебаг, всё дело в конструкции if (sr.Attr and FileAttrs) = sr.Attr then. По не совсем понятным мне причинам все файлы в личной папке пользователя имеют в атрибуте кроме младшего байта ненулевое значение и в байте постарше. Если в остальных директориях например для директорий sr.Attr был равен $00000010, то в личной папке пользователя он оказывается равен $00002010. Соответсвенно операция ($00002010 and $00000010) = $00002010 никогда не будет правдивой.

Исправил ситуацию заменой конструкции на:
if (sr.Attr and FileAttrs) <> 0 then

"Digital Networked Knight"
Ерёмин А.А.
Ерёмин А.А.
*Администратор
Сообщения: 435
[Сообщение #2] 29 февраля 2012, 14:31
Могу ошибаться, но по-моему компилятор выдавал предупреждение, что данные зависят от установленной ОС. Может и не в поиске, но где-то при работе с файлами точно встречался.

DNK
DNK
Студент
Сообщения: 242
[Сообщение #3] 29 февраля 2012, 14:51
"... is specific to a platform"? Не было такого. Конкретно я такую ругарь видел только на модуль FileCtrl, а функции поиска используют SysUtils.
Да даже если и так, ты как-то по другому список файлов получаешь?

"Digital Networked Knight"
Ерёмин А.А.
Ерёмин А.А.
*Администратор
Сообщения: 435
[Сообщение #4] 29 февраля 2012, 14:59

Цитата (DNK):

Конкретно я такую ругарь видел только на модуль FileCtrl

Вполне возможно. Я помню, что видел где-то в местах, связанных с файлами.

Цитата (DNK):

Да даже если и так, ты как-то по другому список файлов получаешь?

Нет. Это уже камни, о которых никто не предупредил. Спасибо за информацию!

bugmenot
bugmenot
3-ий класс
Сообщения: 88
[Сообщение #5] 1 марта 2012, 11:02
Сам ты ахтунг ;-)
Этому [кривенькому] примеру поболее 15 лет будет

А тот бит, который всю Delphi-малину поломал присутствует тоже уже много лет

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

DNK
DNK
Студент
Сообщения: 242
[Сообщение #6] 1 марта 2012, 12:06
И всё таки я хотел заострить на нем внимание. Работаю с Delphi больше 10 лет, а о такой тонкости узнал впервые и уверен многие о ней до сих пор не подозревают.

За ссылку спасибо.

"Digital Networked Knight"
bugmenot
bugmenot
3-ий класс
Сообщения: 88
[Сообщение #7] 2 марта 2012, 16:57
Да нет же здесь никакой тонкости. Есть неряшливый старый код, который когда-то работал, а теперь сломался. Он сломался бы и раньше, если бы кто-то озаботился его протестировать.

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

Вадим К
Вадим К
Академик
Сообщения: 85
[Сообщение #8] 13 марта 2012, 18:38
 if (sr.Attr and FileAttrs) = sr.Attr then
А кто сказал, что этот код верный? он точно неверный и от винды это мало зависит. Просто раньше везло.
Если присмотрется, то этот код эквивалентный такому
 if sr.Attr = FileAttrs then
В условии задачи ведь говорится, что код будет искать файлы, которые имеют указанные атрибуты.
Но кто мешает файлам иметь другие атрибуты.
А хотелось проверить, что файл имеет эти атрибуты, и возможно другие. Ну тогда зачем добавлять условие??? findfirst и так все правильно отберет.

with StringGrid1 do
  begin
    RowCount := 0;
    if FindFirst(Edit1.Text, FileAttrs, sr) = 0 then begin
      repeat
        RowCount := RowCount + 1;
        Cells[1,RowCount-1] := sr.Name;
        Cells[2,RowCount-1] := IntToStr(sr.Size);
      until FindNext(sr) <> 0;
      FindClose(sr);
    end;
  end;
Но да, некоторые любят писать перестраховочный код. Но писать его не могут.

Галочка "подтверждения прочтения" - вселенское зло.
DNK
DNK
Студент
Сообщения: 242
[Сообщение #9] 13 марта 2012, 19:06
Я может чего-то не догоняю. У меня Delphi глубоко накласть, какой атрибут передают в FindFirst. Указываю искать только каталоги, но всё равно находятся и обычные файлы удовлетворяющие текстовой маске.

Цитата (Вадим К):

Если присмотрется, то этот код эквивалентный такому
 if sr.Attr = FileAttrs then
А в случае faAnyFile?

"Digital Networked Knight"
Вадим К
Вадим К
Академик
Сообщения: 85
[Сообщение #10] 14 марта 2012, 12:23
Читаем, ужасаемся
http://xydan.livejournal.com/2762.html

Галочка "подтверждения прочтения" - вселенское зло.

Страницы: «1» «2» (всего страниц: 2, текущая: 1)
Всего сообщений: 12 (сейчас показаны: с 1 по 10)

Перейти в раздел:


 © 2004 - 2025, Delphi.int.ru
Версия форума: 1.10 (19.01.2010)
RSS Delphi.int.ru Expert Код
Выполнено за 0.03 сек.
Обратная связь