Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Dateigröße ermitteln, wie geht Ihr vor? (https://www.delphipraxis.net/195004-dateigroesse-ermitteln-wie-geht-ihr-vor.html)

Fukiszo 25. Jan 2018 21:29

Dateigröße ermitteln, wie geht Ihr vor?
 
Hi, hier ein beispiel wie ich es mit Delphi mache

Delphi-Quellcode:
// return -1 if file not found else size in byte
function lwFileSize(sFileToExamine: string) : Longint;
var
  fFile : file of Byte;
begin
  Result := -1;
  if FileExists(sFileToExamine) then
  try
    FileMode := 0;
    AssignFile(fFile, sFileToExamine);
    Reset(fFile);
    Result := FileSize(fFile);
  finally
    Close(fFile);
  end;
end;
ist diese art und weise veraltet und überholt?

Grüße

ps: ich wusst nicht wohin deshalb ist es hier gelandet.

LTE5 25. Jan 2018 21:41

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
So ist es um einiges schneller

Delphi-Quellcode:
function lwFileSize(const aFileName: string): Int64;
var
 FileInfo: TWin32FileAttributeData;
begin
 Result := -1;

 FillChar(FileInfo, SizeOf(FileInfo), 0);
 if GetFileAttributesEx(PChar(aFileName), GetFileExInfoStandard, @FileInfo) then
  begin
   Int64Rec(Result).Hi := FileInfo.nFileSizeHigh;
   Int64Rec(Result).Lo := FileInfo.nFileSizeLow;
  end;
end;

Fukiszo 25. Jan 2018 23:06

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
danke für deinen vorschlag, ich versuche das was jetzt kommt in eine delphi ide vcl variante umzubauen,
das liest ein verzeichniss ein und gibt dateien in eine ListView mit icon und paar info's wieder.

Delphi-Quellcode:
procedure GetFiles(const hLV: HWND; Path, Mask: String);
var
  finddata : TWin32FindData;
  hFile   : cardinal;
  Loop    : dword;
  lvi     : TLVItem;
  buf     : array[0..25]of char;
  tile    : TLVTileInfo;
  fi      : TSHFileInfo;
  LVIMark : TLVInsertMark;
  tmp     : String;
  i       : integer;
begin
 hFile := FindFirstFile(PChar(IncludeTrailingPathDelimiter(Path) + Mask), finddata);
  if(hFile <> INVALID_HANDLE_VALUE) then begin
   LockWindowUpdate(hDlg);
   LastFolder := IncludeTrailingPathDelimiter(Path);
   Loop := 0;
    repeat
     if(finddata.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY = 0) then begin

      ZeroMemory(@fi, sizeof(TSHFileInfo));
      ListView_SetImageList(hLV,
       SHGetFileInfo(PChar(IncludeTrailingPathDelimiter(Path) + finddata.cFilename), 0,
       fi, sizeof(TSHFileInfo), SHGFI_SYSICONINDEX or SHGFI_TYPENAME or SHGFI_SMALLICON), LVSIL_SMALL);

      ZeroMemory(@fi, sizeof(TSHFileInfo));
      ListView_SetImageList(hLV,
       SHGetFileInfo(PChar(IncludeTrailingPathDelimiter(Path) + finddata.cFilename), 0,
       fi, sizeof(TSHFileInfo), SHGFI_SYSICONINDEX or SHGFI_TYPENAME or SHGFI_ICON), LVSIL_NORMAL);

      lvi.mask    := LVIF_TEXT or LVIF_IMAGE;
      lvi.iItem   := Loop;
      lvi.iSubItem := 0;
      lvi.pszText := finddata.cFileName;
     i := 0;
      lvi.iImage  := fi.iIcon;
      ListView_InsertItem(hLV, lvi);

      tmp := IntToStr(finddata.nFileSizeLow)+' byte';
      if (finddata.nFileSizeLow / 1024) > 1 then tmp := FloatToStr((finddata.nFileSizeLow / 1024),-1,2)+' kb';
      if (finddata.nFileSizeLow / 1024 / 1024) > 1 then tmp := FloatToStr((finddata.nFileSizeLow / 1024 / 1024),-1,2)+' mb';
      if (finddata.nFileSizeLow / 1024 / 1024 / 1024) > 1 then tmp := FloatToStr((finddata.nFileSizeLow / 1024 / 1024 / 1024),-1,2)+' gb';
      lvi.mask    := LVIF_TEXT;
      lvi.iSubItem := 1;
      lvi.pszText := pChar(tmp);
      ListView_SetItem(hLV, lvi);

      lvi.mask    := LVIF_TEXT;
      lvi.iSubItem := 2;
      lvi.pszText := fi.szTypeName;
      ListView_SetItem(hLV, lvi);

//      ZeroMemory(@buf, sizeof(buf));
//      wvsprintf (buf, '%u byte', pchar(@finddata.nFileSizeLow));
      lvi.mask    := LVIF_TEXT;
      lvi.iSubItem := 3;
      lvi.pszText := pChar(IntToStr(finddata.nFileSizeLow)); //buf;
      ListView_SetItem(hLV, lvi);

     if GetOSVersion = osXP then begin
      tile.cbSize   := sizeof(TLVTileInfo);
      tile.iItem    := Loop;
//     tile.cColumns := length(colArray);
      tile.puColumns := @colArray[0];
      ListView_SetTileInfo(hLV, tile);
     end;
    LVIMark.cbSize    := sizeof(TLVInsertMark);
    LVIMark.dwFlags   := LVIM_AFTER;
    LVIMark.iItem     := Loop;
    LVIMark.dwReserved := 0;
    ListView_SetInsertMark(hLV, LVIMark);
    if LowerCase(ExtractFileName(SelectedFile)) = LowerCase(finddata.cFileName) then
    begin
{     if LowerCase(ExtractFileName(SelectedFile)) = LowerCase(finddata.cFileName) then
      ListView_SetItemState(hLV, Loop, 0, LVIS_SELECTED);}
      lvi.stateMask := LVIS_SELECTED;
      lvi.state := LVIS_SELECTED;
      SendMessage(hLV, LVM_SETITEMSTATE, Loop, Longint(@lvi))
    end;
    Inc(Loop);
   end;
  until (not FindNextFile(hFile, finddata));
   FindClose(hFile);
  LockWindowUpdate(0);
 end;
end;
vielleicht kann man das auch "tunen" ?

Grüße

LTE5 25. Jan 2018 23:32

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
Hier würde ich ein VirtualStringTree verwenden.

Der schöne Günther 26. Jan 2018 09:41

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
Ich mache es haargenau gleich wie LTE5

Delphi-Quellcode:
class function TFileHelper.GetSize(const fileName: String): Int64;
var
   info: TWin32FileAttributeData;
begin
   if not TFile.Exists(fileName) then
      raise EFileNotFoundException.CreateRes(@SFileNotFound);

   // Quelle: http://stackoverflow.com/a/1642355/2298252
   if not GetFileAttributesEx(
      PChar(fileName),
      WinApi.Windows.GetFileExInfoStandard,
      Addr(info)
   ) then RaiseLastOSError();

   Result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32);
end;

himitsu 26. Jan 2018 09:58

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
Warum doppelt abfragen?
Delphi-Quellcode:
class function TFileHelper.GetSize(const fileName: String): Int64;
var
   info: TWin32FileAttributeData;
begin
   if not GetFileAttributesEx(PChar(fileName), GetFileExInfoStandard, @info) then
     RaiseLastOSError;
   Result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32);
end;
Wenn es aber unbedingt EFileNotFoundException sein soll, dann halt
Delphi-Quellcode:
class function TFileHelper.GetSize(const fileName: String): Int64;
var
   info: TWin32FileAttributeData;
begin
   if not GetFileAttributesEx(PChar(fileName), GetFileExInfoStandard, @info) then
     if GetLastError in [ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND] then
       raise EFileNotFoundException.CreateRes(@SFileNotFound)
     else
       RaiseLastOSError;
   Result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32);
end;

freimatz 26. Jan 2018 10:29

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
@Fukiszo: Empfehle http://www.delphipraxis.net/162373-t...t-ihr-vor.html

Fukiszo 26. Jan 2018 11:47

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
Danke für all eure Vorschläge und Mühe

Code:
// von LTE5
function lwFileSize(const aFileName: string): Int64;
var
 FileInfo: TWin32FileAttributeData;
begin
 Result := -1;
 FillChar(FileInfo, SizeOf(FileInfo), 0); // das hier evtl weglassen, muss ich selbst erst nachvollziehen können warum
 if GetFileAttributesEx(PChar(aFileName), GetFileExInfoStandard, @FileInfo) then
  begin
   Int64Rec(Result).Hi := FileInfo.nFileSizeHigh;
   Int64Rec(Result).Lo := FileInfo.nFileSizeLow;
  end;
end;
das hier klappt wie gewünscht (bei "file not found" = -1) für mich und die routine arbeitet wirklich schneller
wobei ich total geneigt bin auch das hier dafür zu verwenden:

Code:
// von mehreren DP teilnehmern, hier kann man rückgabewert verintensivieren
// (für externe fehlerbestimmung ist's so besser, sonst evtl dutzende fehlermeldungen falls in einer loop aufgerufen)
// -1 file not found
// -2 general error
// >= 0 filesize in byte
function lwFileSize(const fileName: String): Int64;
var
   info: TWin32FileAttributeData;
begin
   if not GetFileAttributesEx(PChar(fileName), GetFileExInfoStandard, @info) then // tatsächlich pChar ja? (Unicode dingens)
     if GetLastError in [ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND] then
       result := -1 //raise EFileNotFoundException.CreateRes(@SFileNotFound)
     else
       result := -2 // RaiseLastOSError;
   Result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32);
end;
Grüße & Danke

himitsu 26. Jan 2018 13:10

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
Wenn es die API GetFileAttributesEx ausschließlich nur als Unicode gäbe, dann PWideChar und ein Unicode-String (den "String" nach Unicode casten).
Schwer zu verstehen ist das ja nun nicht wirklich:
GetFileAttributesEx + PChar + String ... natürlich nur, wenn diese Funktion auch compilerabhänig deklariert wurde.
GetFileAttributesExA + PAnsiChar + AnsiString
GetFileAttributesExW + PWideChar + WideString/UnicodeString

Als Funktion existiert "GetFileAttributesEx" ja eigentlich garnicht. Nur als "unabhängige" Definition.
Delphi-Quellcode:
function GetFileAttributesEx(lpFileName: PChar; fInfoLevelId: TGetFileExInfoLevels; lpFileInformation: Pointer): BOOL; stdcall;
function GetFileAttributesExA(lpFileName: PAnsiChar; fInfoLevelId: TGetFileExInfoLevels; lpFileInformation: Pointer): BOOL; stdcall;
function GetFileAttributesExW(lpFileName: PWideChar; fInfoLevelId: TGetFileExInfoLevels; lpFileInformation: Pointer): BOOL; stdcall;

function GetFileAttributesEx; external kernel32 name {$IFDEF UNICODE}'GetFileAttributesExW'{$ELSE}'GetFileAttributesExA'{$ENDIF};
function GetFileAttributesExA; external kernel32 name 'GetFileAttributesExA';
function GetFileAttributesExW; external kernel32 name 'GetFileAttributesExW';

Sowas ist auch immer ganz nett.
Delphi-Quellcode:
GetFileSize(const aFileName: string; NoException: Boolean=False): Int64;
Ausnahmen behandle ich gern auch als Exceptions.
Wenn die Datei nicht existiert, deren Datum ich wissen will, dann ist das eine Ausnahme.

Aber falls ich doch mal prüfen will und es mit erstmal egal ist, ob die Datei existiert, dann kann man so die Exception deaktivieren, ohne ein Try-Except drummachen zu müssen.

LTE5 26. Jan 2018 14:47

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
Zitat:

Wenn es die API GetFileAttributesEx ausschließlich nur als Unicode gäbe, dann PWideChar und ein Unicode-String (den "String" nach Unicode casten).
Schwer zu verstehen ist das ja nun nicht wirklich:
GetFileAttributesEx + PChar + String ... natürlich nur, wenn diese Funktion auch compilerabhänig deklariert wurde.
GetFileAttributesExA + PAnsiChar + AnsiString
GetFileAttributesExW + PWideChar + WideString/UnicodeString

Als Funktion existiert "GetFileAttributesEx" ja eigentlich garnicht. Nur als "unabhängige" Definition.
Was möchtest du damit nun sagen?

Fukiszo 26. Jan 2018 16:57

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
das war an mich gemeint wegen dem unicode.
nicht das ich diesen tipp weitergebe ohne das berücksichtigt zu haben.
ich habs jedenfalls so aufgenommen als hinweis für mich da ich oft pChar einsetz wo es anders lauten sollte.

Grüße

LTE5 26. Jan 2018 17:00

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
Ist es nicht egal, ob PChar oder PWideChar oder sonst was?
Ich kenne das nur so, dass PChar über allem steht.

himitsu 26. Jan 2018 17:03

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
Nein, ist nicht egal.

PChar/Char/String sind compilerabhängig, also können sich ändern.
Wenn es also nicht zusammenpasst, dann kann es schnell knallen.

z.B. bei diesem Code hier PWideChar verwendet und schon gibt es in Delphi 2-2007 und in FreePascal probleme, wenn String und GetFileAttributesEx dort plötzlich ANSI sind, im Gegensatz zu Delphi 2009+.

PChar ist ein Alias, der je nach Compiler z.B. auf PAnsiChar oder PWideChar verweist.

LTE5 26. Jan 2018 17:07

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
Zitat:

z.B. bei diesem Code hier PWideChar verwendet und schon gibt es in Delphi 2-2007 und in FreePascal probleme
Ich bin einfach stillschweigend davon ausgegangen, dass keiner mehr diese Krankheiten vor D2009 benutzt ;)

Fukiszo 26. Jan 2018 17:12

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
ich finds spannend dazuzulernen, da in meinen erste source code post's noch vieles per pChar werkelte und ich daraufhin zu weiteren links zu diesem thema verwiesen haben, hab ich hier http://docwiki.embarcadero.com/RADSt..._in_RAD_Studio und hier http://docwiki.embarcadero.com/RADSt...icode_anpassen meine kleinen ratgeber in bezug auf unicode gefunden. kann auch abende füllen sich da durchzuarbeiten (noch ein link, noch mehr input ...) aber macht spass.

in diesem sinne,

grüße

edit ps:
ich nutz delphi version 7 von anno dazumal und bin glücklich damit auch wenn ich kostenfrei ein aktuelles bekommen könnte.

HolgerX 26. Jan 2018 17:13

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
Hmm..


Wieso dann nicht gleich Typfixiert?

Delphi-Quellcode:
function GetSize(const fileName: WideString): Int64;
var
   info: TWin32FileAttributeData;
begin
   if not GetFileAttributesExW(PWideChar(fileName), GetFileExInfoStandard, @info) then
     RaiseLastOSError;
   Result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32);
end;
Dies funktioniert unter allen Delphi-Versionen, welche WideChar unterstützen (somit eigentlich fast alle ;) )

Edit:
Für alle API-Funktionen verwende ich nur noch die Wide Versionen. Somit gibt es auch keine Probleme..

LTE5 26. Jan 2018 17:16

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
Gerade die Suche bemüht. Mach dir da keinen Kopf und benutz einfach PChar wenn du keine alten Delphiversionen <2009 mehr benutzt
http://www.delphipraxis.net/1385162-post6.html

Fukiszo 26. Jan 2018 17:32

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
Jupp.

Zitat:

Delphi definiert bei WinAPIs auch in der Regel z.b. MessageBoxA , MessageBoxW und dann einmal noch nur MessageBox , welches dann auf eine der beiden Varianten verweist. Dadurch brauchst du dir über A/W keine Gedanken machen und einfach MessageBox(PChar(), ...) aufrufen. Willst du in irgendeinem Falle mal eine explizite Version, dann solltest du auch den Typen in die explizite Form casten: MessageBoxA(PAnsiChar(), ...) .
das bringt es auf den punkt:thumb:

Bernhard Geyer 26. Jan 2018 17:58

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
Zitat:

Zitat von LTE5 (Beitrag 1392175)
Ich bin einfach stillschweigend davon ausgegangen, dass keiner mehr diese Krankheiten vor D2009 benutzt ;)

:thumb: +1 8-)

Aber ich glaube du wirst gleiche von bekannten Usern verbal gesteinigt ...

LTE5 26. Jan 2018 18:56

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
Um meiner Steinigung zuvor zu kommen:
sollte dieser bekannte user Windows 10 nutzen, darf er mich schlicht weg nicht steinigen. Er darf es nur, wenn er noch Windows XP nutzt.

Bernhard Geyer 27. Jan 2018 09:32

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
Zitat:

Zitat von LTE5 (Beitrag 1392188)
Er darf es nur, wenn er noch Windows XP nutzt.

Eher wenn er noch Win95/98/ME benutzt. Den diese haben nur die Ansi-Version der Windows-API.
Die Wide-Version der API gibt es seit NT 1.0 (auch wenn dort noch viele heutige Funktionen gefehlt haben).
Die o.g. GetFileAttributesExW gibts z.B. ab XP.

LTE5 27. Jan 2018 10:57

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
Den vergleich mit der Windowsversion habe ich eigentlich ganz anders gemeint und der hatte absolut nichts mit den Datentypen zu tun.
Naja egal.

Fukiszo 27. Jan 2018 11:50

AW: Dateigröße ermitteln, wie geht Ihr vor?
 
falls das eine rolle spielt, ich nutze privat windows version 7 64bit mit delphi version 7 32bit. windows 10 hab ich in einer vm aber bin selbst davon nicht so überzeugt als das es mein OS ersetzt, per internet vm kann ich auch mit radstudio xe 10.2.2 herumspielen wenn's denn sein muss.

Grüße

edit
ps: eine vm mit windows xp und windows 98SE hab ich auch noch, wobei letztere bestimmt schon paar jahre nicht mehr gestartet wurde.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:10 Uhr.

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