Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Access violation bei der Auflistung von Dateien (https://www.delphipraxis.net/85234-access-violation-bei-der-auflistung-von-dateien.html)

fdsgbla 27. Jan 2007 18:49


Access violation bei der Auflistung von Dateien
 
Warum kommt es bei der Funktion:

Delphi-Quellcode:
function VerzGroesse(Verzeichnis:string):longint;
var SR     : TSearchRec;
    Groesse : longint;
begin
  Groesse:=0;
  if Verzeichnis[length(Verzeichnis)]<>'\' then
    Verzeichnis:=Verzeichnis+'\';
  if FindFirst(Verzeichnis+'*.*',$3F,SR)=0 then begin
    repeat
      if ((SR.Attr and faDirectory)>0) and (SR.Name<>'.') and (SR.Name<>'..') then
        Groesse:=Groesse+VerzGroesse(Verzeichnis+SR.Name)
      else
        Groesse:=Groesse+SR.Size;
      if (SR.Name<>'.') and (SR.Name<>'..') then
        FileListArray.Add(Verzeichnis+SR.Name);
    until FindNext(SR)<>0;
    FindClose(SR);
  end;
  Result:=Groesse;
end;
(stammt von http://www.delphi-fundgrube.de/faq03.htm#topic0310)

zu "Access violation" - Fehler

sie wird mit:
Delphi-Quellcode:
self.caption := IntToStr(VerzGroesse('C:\Program Files\'))+' Byte';
aufgerufen. Der Ordner "Program Files" existiert und ist nicht leer.

SirThornberry 27. Jan 2007 18:56

Re: Access violation bei der Auflistung von Dateien
 
die einzige Stelle wo der Fehler auftreten kann ist bei
Delphi-Quellcode:
FileListArray.Add(Verzeichnis+SR.Name);
FileListArray ist vermutlich nicht initialisiert.

fdsgbla 27. Jan 2007 19:09

Re: Access violation bei der Auflistung von Dateien
 
Zitat:

Zitat von SirThornberry
die einzige Stelle wo der Fehler auftreten kann ist bei
Delphi-Quellcode:
FileListArray.Add(Verzeichnis+SR.Name);
FileListArray ist vermutlich nicht initialisiert.

so war es auch. Danke!!!!!!

Hawkeye219 27. Jan 2007 19:28

Re: Access violation bei der Auflistung von Dateien
 
Hallo,

du solltest auch beachten, daß die Routine bei Verzeichnisgrößen ab 2 GB falsche Werte liefert, weil sie alle Berechnungen mit dem Typ longint durchführt. Damit auch größere Verzeichnisse verarbeitet werden können, muß zunächst überall "longint" durch "int64" ersetzt werden. Wird der Code mit einer Delphi-Version vor Delphi 2006 übersetzt, muß eine weitere Zeile angepaßt werden:

Delphi-Quellcode:
// Groesse := Groesse + SR.Size;
Groesse := Groesse + Int64(SR.FindData.nFileSizeHigh) shl 32 + SR.FindData.nFileSizeLow;
Gruß Hawkeye

fdsgbla 27. Jan 2007 19:41

Re: Access violation bei der Auflistung von Dateien
 
Zitat:

Zitat von Hawkeye219
Hallo,

du solltest auch beachten, daß die Routine bei Verzeichnisgrößen ab 2 GB falsche Werte liefert, weil sie alle Berechnungen mit dem Typ longint durchführt. Damit auch größere Verzeichnisse verarbeitet werden können, muß zunächst überall "longint" durch "int64" ersetzt werden. Wird der Code mit einer Delphi-Version vor Delphi 2006 übersetzt, muß eine weitere Zeile angepaßt werden:

Delphi-Quellcode:
// Groesse := Groesse + SR.Size;
Groesse := Groesse + Int64(SR.FindData.nFileSizeHigh) shl 32 + SR.FindData.nFileSizeLow;
Gruß Hawkeye

Auch Danke

Zählt TurboDelphi auch zu Delphi 2006?

mkinzler 27. Jan 2007 19:43

Re: Access violation bei der Auflistung von Dateien
 
Zitat:

Zählt TurboDelphi auch zu Delphi 2006?
Ja.

Christian Seehase 27. Jan 2007 20:41

Re: Access violation bei der Auflistung von Dateien
 
Moin fdsgbla,

mal abgesehen von dem 2GB Problem hat die Routine noch ein paar mehr:

Delphi-Quellcode:
function VerzGroesse(Verzeichnis:string):longint;
var SR     : TSearchRec;
    Groesse : longint;
begin
  Groesse:=0;
  // Wenn Verzeichnis = '' => AV
  if Verzeichnis[length(Verzeichnis)]<>'\' then
    Verzeichnis:=Verzeichnis+'\';
  // Warum $3F, wenn es dafür eine Konstante gibt (faAnyfile)
  if FindFirst(Verzeichnis+'*.*',$3F,SR)=0 then begin
   // Es fehlt try/finally um die Ausführung von FindClose abzusichern,
   // wenn FindFirst erfolgreich war
    repeat
      // > 0 funktioniert hier zwar, besser ist aber <> 0
      // oder = faDirectory. Der Wert könnte auch negativ sein
      if ((SR.Attr and faDirectory)>0) and (SR.Name<>'.') and (SR.Name<>'..') then
        Groesse:=Groesse+VerzGroesse(Verzeichnis+SR.Name)
      else
        Groesse:=Groesse+SR.Size;
      // Da . und .. immer Verzeichnisse sind gehört das auch in die
      // vorherige if-Abfrage
      if (SR.Name<>'.') and (SR.Name<>'..') then
        FileListArray.Add(Verzeichnis+SR.Name);
    until FindNext(SR)<>0;
    FindClose(SR);
  end;
  Result:=Groesse;
end;
Es sollte besser so (oder ähnlich aussehen):

Delphi-Quellcode:
function VerzGroesse(Verzeichnis:string):longint;
var SR     : TSearchRec;
    Groesse : longint;
begin
  Groesse:=0;
  if (Length(Verzeichnis) > 0) and Verzeichnis[length(Verzeichnis)]<>'\' then Verzeichnis:=Verzeichnis+'\';
  if FindFirst(Verzeichnis+'*.*',faAnyFile,SR) = 0 then begin
    try
      repeat
        if ((SR.Attr and faDirectory) <> 0) and (SR.Name <> '.') and (SR.Name <> '..') then begin
          Groesse:=Groesse+VerzGroesse(Verzeichnis+SR.Name);
          FileListArray.Add(Verzeichnis+SR.Name);
        end else begin
          Groesse:=Groesse+SR.Size;
        end;
      until FindNext(SR)<>0;
    finally
      FindClose(SR);
    end;
  end;
  Result:=Groesse;
end;
Wobei auch diese Variante möglich wäre

Delphi-Quellcode:
function VerzGroesse(Verzeichnis:string):longint;
var SR     : TSearchRec;
    Groesse : longint;
begin
  Groesse:=0;
  if FindFirst(Verzeichnis+'\*.*',faAnyFile,SR) = 0 then begin
    try
      repeat
        if ((SR.Attr and faDirectory) <> 0) and (SR.Name <> '.') and (SR.Name <> '..') then begin
          Groesse:=Groesse+VerzGroesse(Verzeichnis+SR.Name);
          FileListArray.Add(Verzeichnis+SR.Name);
        end else begin
          Groesse:=Groesse+SR.Size;
        end;
      until FindNext(SR)<>0;
    finally
      FindClose(SR);
    end;
  end;
  Result:=Groesse;
end;
da mehrere aufeinander folgende Pfadtrenner (\) nicht stören, so dass Verzeichnis auf \ enden, und man trotzdem die Suchmaske \*.* verwenden kann.

Hawkeye219 27. Jan 2007 21:06

Re: Access violation bei der Auflistung von Dateien
 
Moin Chris,

Zitat:

Zitat von Christian Seehase
[...]da mehrere aufeinander folgende Pfadtrenner (\) nicht stören[...]

mehrere aufeinander folgende nicht, ein vergessener schon:

Delphi-Quellcode:
// Groesse:=Groesse+VerzGroesse(Verzeichnis+SR.Name);
// FileListArray.Add(Verzeichnis+SR.Name);
Groesse:=Groesse+VerzGroesse(Verzeichnis+'\'+SR.Name);
FileListArray.Add(Verzeichnis+'\'+SR.Name);
Gruß Hawkeye

Christian Seehase 27. Jan 2007 21:12

Re: Access violation bei der Auflistung von Dateien
 
Moin Hawkeye,

da hast Du auch wieder recht. :wall:

fdsgbla 27. Jan 2007 21:14

Re: Access violation bei der Auflistung von Dateien
 
Nochmals Danke :wink:


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:21 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz