Newsgroup: it.comp.lang.delphi
Titolo: Simpatico bug in FindFirst/FindNext

Giusto per farvelo sapere, ho trovato un altro bel buggettino in queste due
funzioni:
facendo
FindFirst('*.plm', faArchive, SR);
mi trova anche i file con estensione .plm_tmp (e presumo con qualsiasi altra
cosa che sia .plm*).
Credo che alla Borland siano secoli che non toccano il codice di queste
funzioni... secondo me sono le stesse del pascal :)
--
Jax
====
La sinistra sono io. (Bettino Craxi)

 funzioni... secondo me sono le stesse del pascal :)
Non so nello specifico questo problema, ma le funzioni findfirst e findnext
si rifanno direttamente a quelle offerte dal kernel di windows... quindi non
credo sia colpa della borland..
Ciao
Matteo

 funzioni... secondo me sono le stesse del pascal :)
come ha gią detto Matteo, le SysUtils.FindFirst, FindNext & C. sono dei 
wrapper di funzioni di Win32: FindFirstFile, FindNextFile & C.
Oppure ci sarebbero anche le chiamate agli interrupt BIOS:
Interrupt 21h Function 714Eh = FindFirstFile
Interrupt 21h Function 714Fh = FindNextFile
Interrupt 21h Function 71A1h = FindClose
Tu su quale S.O. hai rilevato il bug?
-- 
Mauro Falzari 
   [ 
http://digilander.libero.it/mauro.falzari
 ]
 
 "Se guardi nell'abisso, anche l'abisso guarda in te." 
   (Friedrich Nietzsche)

 Tu su quale S.O. hai rilevato il bug?
Sono interrupt DOS/Windows, non BIOS.  In ogni caso, dubito che siano
invocabili direttamente senza scatenare un "Privileged Instruction".
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

invocabili direttamente senza scatenare un "Privileged Instruction".
tra l'altro in tempi di "irrigidimento" come questi, dove si parla di .net e
palladium, parlare di interrupt e' come dire le parolacce in chiesa...
-- 
Morde. 
(
mo...@despammed.com
)

 invocabili direttamente senza scatenare un "Privileged Instruction".
e se uno li chiamasse sotto Win9x?


 e se uno li chiamasse sotto Win9x?
Idem, il problema non è l'ambiente in cui li chiami, ma *chi* li chiama.


 Tu su quale S.O. hai rilevato il bug?
Non lo sospettavo, infatti non sono manco andato a vedere i sorgenti...
Comunque, me lo fa su Win2000 sp4.
--
Jax
====
Dicono che sbagliando si impara, allora lasciatemi sbagliare.

 me lo fa su Win2000 sp4.
ho voluto provare anche io e a me lo fa su WinXp.
A questo punto, per controllare che effettivamente il file corrisponda a ciň 
che stai cercando, dovrai effettuare anche un controllo sulla lunghezza del 
nome.


però è strano, perchè dati tre file
1) Unit1.pla
2) Unit1.pla_A
3) Unit1.pla_AXYZ
- impostando la FindFirst col filtro *.pla o *.PLA vengono restituiti tutti e 
tre;
- con filtro *.pl non viene restituito nessuno mentre ci si aspettava (visto 
il comportamento di sopra) che venissero trovati tutti e tre i file;
- con filtro *.pla_ non viene restituito nessuno mentre ci si aspettava due 
file;
- con filtro *.pla_A o *.pla_a viene trovato solo il file n. 2) mentre ci 
aspettavamo che fossero trovati due file (il n. 2 e il n. 3);
- con filtro *.pl* come ci aspettavamo vengono trovati tutti e tre.
Mah!!


eh no, eh no, eh no..
la cosa è ancora più oscura!
Ho fatto delle prove con entrambi i sistemi e i problemi si complicano.
Supponi di avere in una cartella questi tre files:
1) Unit1.pla
2) Unit1.pla_A
3) Unit1.pla_AXYZ
poi in una form nuova mettici un Memo e mettici questo codice (poi leggi 
in fondo al post):
procedure TForm1.FormCreate(Sender: TObject);
const
  FILTER = '*.pla';
begin
//fai le prove qui, togliendo i commenti a una o l'altra funzione
//  Con SysUtils.FindFirst:
//  GetFiles(FILTER, Memo1.Lines);
//  Con Windows.FindFirstFile:
  GetFiles_Win32(FILTER, Memo1.Lines);
end;
procedure TForm1.GetFiles(const Filter: string; Strings: TStrings);
const
  FOUND = 0;
var
  srResult: TSearchRec;
begin
  Strings.Clear;
  if FindFirst(Filter, faArchive, srResult) = FOUND then
    try
      repeat
        Strings.Add(srResult.Name);
      until FindNext(srResult) <> FOUND
    finally
      FindClose(srResult);
    end
end;
procedure TForm1.GetFiles_Win32(const Filter: string; Strings: TStrings);
var
  F: WIN32_FIND_DATA;
  hFile: THandle;
begin
  Strings.Clear;
  hFile:= FindFirstFile(PChar(Filter), F);
{ FindFirstFile: This function searches for files by name only;
  it cannot be used for attribute-based searches. }
  if hFile <> INVALID_HANDLE_VALUE then
    try
      repeat
        Strings.Add(F.cFileName);
      until FindNextFile(hFile, F) <> False;
    finally
      Windows.FindClose(hFile);
    end
end;
//////////////////////////////////////////////////////
Ora con 
FILTER = '*.pla' va tutto bene (viene trovato un solo file)
ma con 
FILTER = '*.pla_A' si entra in un loop infinito perchè il file Unit1.pla_A 
viene trovato infinite volte
e con
FILTER = '*.pla_A*' non viene trovato nulla!!!
Io non ci sto capendo più niente...


 complicano.
Mi sembra sia sbagliata la tua condizione di uscita dal repeat:
prova con 2 memo la versione VCL e la Win32.
procedure GetFilesWin32(const Filter: string; dest: TStrings);
var fd: TWin32FindData;
    h: THandle;
begin
  dest.Clear;
  h := FindFirstFile(PChar(Filter), fd);
  if h <> INVALID_HANDLE_VALUE then try
    repeat
      dest.Add(fd.cFileName);
    until not FindNextFile(h, fd);    // <---
  finally
    Windows.FindClose(h)
  end;
end;
Saluti
Paolo Arosio
-- 
"La dimostrazione dell'esistenza di specie intelligenti nell'universo
 e' che non ci vengono a trovare"

Non vorrei dire fesserie , ma credo potrebbe dipendere dal fatto che
l'estensione "tradizionale" sia di soli tre caratteri.
Giulio

 l'estensione "tradizionale" sia di soli tre caratteri.
Quasi sicuramente dipende da quello, ma *in teoria* il concetto di long file
name avrebbe dovuto essere una cosa naturale da win95 in poi.
--
Jax
====
Nell'amore non bisogna mai affrettare il piacere. (Ovidio)

cosa che sia .plm*).
Questa è una cosa simile a quella che avevo segnalato circa una
settimana fa: 
http://groups.google.it/groups?q=simone+murdock+bug+findnext+it+delphi&hl=it&lr=&ie=UTF-8&oe=UTF-8&selm=mthctvs2e78cnjccne2s3ampkjddutn61m%404ax.com&rnum=1
il filtro "*ad*"  mi riportava "casA Di cura" (anche aumentando di
numero gli spazi interposti), mentre usando questo filtro con la
funzione "nativa" di Windows [2000 SP4] (ad esempio dall'ambiente IDE di
Borland con il menu File -> Apri) tutto funzionava regolarmente.
Postando lo stesso quesito su alt.comp.lang.borland-delphi, mi hanno
risposto che ne avevano già discusso un mese prima:
 
http://groups.google.com/groups?th=9b473aedfcbef6e9
In tal caso il quesito era:
"Under D7 I'm using the FindFirst / FindNext functions to find my local
HTML files, for which I use the mask "*.htm". Now I also get files with
the extension ".html"."
 ed hanno risposto:
"Extensions of long files names are indeed truncated to three
characters. 
I don't really consider it a bug, though. The short file name is just as
valid as the long one, so how is FindFirst supposed to know which you 
want? The TWin32FindData record returned contains both names. 
The filtering abilities of FindFirst are so limited already that I don't
think the added task of confirming a three-character file-name extension
makes much of a difference. You could use the PathMatchSpec API function
to compare the returned name against the desired mask."
In merito al mio quesito hanno invece risposto che: 
"Some people believed it to be a bug, but I disagreed. (Regardless, it 
isn't new; D6's FindFirst shouldn't be significantly different from any 
other Delphi version's since they all call the FindFirstFile API 
function.) The short version of your file name is probably 
"casadi~1.url", which does match your "*ad*.url" file mask. 
FindFirstFile doesn't know which of the file's names you mean to search 
on, so it checks both. If you want a more stringent search, then filter 
the results afterward, just like you would if you were searching based 
on file attributes."
ed un altro:
"It is probably because the FindFirst/FindNext is designed to get files
whose long file name OR short file name match the parameter.  If you
do a DIR at the command line, it will probably behave this way too."
Dunque parrebbe un discorso legato alla compatibilità con i nomi
brevi...boh!
Fatto sta che mi è toccato fare un controllo ulteriore sui dati
riportati! :-((
Una curiosità che non conoscevo: è possibile da registro dire se
generare o no i nomi corti per i file nuovi:
http://www.winguides.com/registry/display.php/2/
"The switch only controls whether new files (or 
newly renamed files) with long names should have short file names 
generated. Long file names that existed before the switch was switched 
will retain their short file names, so your program would still need to 
be aware of short-file-name entries in the directory indices.
It is an NTFS drive. It certainly does not generate short file names."
Mi scuso dei tanti (troppi) scritti in inglese ma tradurre tutta 'sta
roba sarebbe un po' lungo (se serve, posso tradurre singoli passaggi).
Simone
_______________________________________________________
 
Sperm: To be fastest doesn't imply that you are smartest.
                   ( by Enrique Herranz )

 poi.
Per la serie: l'informatica e' la scienza del "dovrebbe"...
In teoria e' cosi', ma un file ha sempre 2 nomi, uno corto e uno lungo,
almeno sotto Win9x. E anche sotto Win2k e successivi probabilmente e' cosi',
per fare in modo che le applicazioni per Windows 16 bit e per DOS vedano
sempre tutti i files indipendentemente dal nome. Almeno, penso che questo
c'entri qualcosa col fatto che la cartella Programmi e la cartella PROGRA~1
sono 2 nomi della stessa cosa...

 roba sarebbe un po' lungo (se serve, posso tradurre singoli passaggi).
molto interessante, invece; ciò chiarisce parecchie cose anche riguardo a 
questo 3ad.


     until not FindNextFile(h, fd);    // <---
hai perfettamente ragione, in effetti avrei dovuto scrivere
FindNextFile(hFile, F) <> True //invece di False
perchè "If the function succeeds, the return value is nonzero. If the 
function fails, the return value is zero."


)  



Figo! 
Non ero a conoscenza del servizio MakeAShorterLink, ma mi ha
impressionato la mia ignoranza sul Message-ID (che faccio anche presto a
recuperare): non si finisce mai di imparare!
Grazie


MakeAShorterLink
Ultimamente io simpatizzo per 
www.tinyurl.com
.
:)
-- 
Morde. 
(
mo...@despammed.com
)

:)
Io invece per 
www.snurl.com
 che ti permette, registrandoti (gratis e senza
chiedere informazioni particolari), di tenere la storia dei tuoi indirizzi
accorciati, poterli modificare e ti dice anche quante volte è stato
utilizzato ogni link ;-)
-- 
Lis
ICQ@Home #7317603sette     ICQ@Work #16285702tre
Mercatino: 
http://snurl.com/sito_lis
Aiuta la ricerca contro il cancro: 
http://snurl.com/ida_team

 FindNextFile(hFile, F) <> True //invece di False
[]
La ragione per cui tendo ad evitare il repeat..until in Pascal. Meglio
assai il do..while del C (o il for, a questo punto).


 Io invece per 
www.snurl.com
Io infine per 
www.urljr.com
 perché fa veramente dei link minuscoli!
Si può inoltre usare come WebService da altre applicazioni, quindi
ancora piu' comodo!
Ciao,
Andrea

ancora piu' comodo!
Mi sono appena iscritto, veramente tosto!!!
-- 
Morde. 
(
mo...@despammed.com
)