Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   TWin32FindData: Dateigröße bestimmen (https://www.delphipraxis.net/190444-twin32finddata-dateigroesse-bestimmen.html)

Jim Carrey 4. Okt 2016 16:26

TWin32FindData: Dateigröße bestimmen
 
Entweder bin ich blind oder doof.

Ich habe eine Prozedur die ein Verzeichnis mit Dateien durchläuft.
Das alles geht über TWin32FindData.

Nun wird mir bei einer 15,6 GB großen ZIP-Datei mit folgender Zeile 3,69 GB ausgegeben:
Delphi-Quellcode:
Groesse := (wfd.nFileSizeHigh * (MAXDWORD)) + wfd.nFileSizeLow;
Ist die Berechnung falsch?

jbg 4. Okt 2016 16:30

AW: TWin32FindData: Dateigröße bestimmen
 
Zitat:

Zitat von Jim Carrey (Beitrag 1349734)
Delphi-Quellcode:
Groesse := (wfd.nFileSizeHigh * (MAXDWORD)) + wfd.nFileSizeLow;
Ist die Berechnung falsch?

MAXDWORD ist ums eins zu klein und du bekommst auch noch einen Integer-Overflow da der Compiler nicht automatisch nach Int64 konvertiert.


Probiere es mal so:
Delphi-Quellcode:
var
  Groesse: Int64;

Groesse := Int64(wfd.nFileSizeHigh) shl 32 + wfd.nFileSizeLow;

Jim Carrey 4. Okt 2016 16:32

AW: TWin32FindData: Dateigröße bestimmen
 
Resultat: 15,69 GB - exakt.
Ich muss mir deine Lösung gleich mal in Ruhe angucken, damit ich sie auch verstehe.
Habe eben auch schon gelesen, dass es ein Limit von 4 GB irgendwo gibt.

Ich bedanke mich! Und ich gucke mir das gleich mal in Ruhe an.

himitsu 4. Okt 2016 16:33

AW: TWin32FindData: Dateigröße bestimmen
 
Zitat:

Zitat von Jim Carrey (Beitrag 1349734)
Delphi-Quellcode:
Groesse := (wfd.nFileSizeHigh * (MAXDWORD)) + wfd.nFileSizeLow;

Ist die Berechnung falsch?

JA

Delphi erweitert Typen automatisch nur auf 32 Bit, solange alle Typen maximal 32 Bit sind, mit dem selben Vorzeichen (SIGNED- und UNSIGNED-Typen)

Das macht der Compiler aus deinem Code:
Delphi-Quellcode:
Groesse := (LongWord(wfd.nFileSizeHigh) * LongWord(MAXDWORD)) + LongWord(wfd.nFileSizeLow);


Aber du willst ja eher
Delphi-Quellcode:
Groesse := (UInt64(wfd.nFileSizeHigh) * LongWord(MAXDWORD)) + LongWord(wfd.nFileSizeLow);

[edit] Natürlich auch das MAXDWORD+1 beachten ... siehe Vorredner

Oder besser noch
Delphi-Quellcode:
Groesse := (UInt64(wfd.nFileSizeHigh) shl 32) or wfd.nFileSizeLow;


Int64 oder UInt64, jenachdem wie
Delphi-Quellcode:
Groesse
deklariert ist (aber es sollte natürlich eher UInt64 sein)

PS: In deinem Fall hättest du den Typ-Fehler sofort gefunden, wenn du in den Projektoptionen einmal die Bereichsprüfung Überlaufprüfung aktiviert hättest.

PS2: Man könnte auch Casten, statt rechnen/schieben -> Int64Rec oder LARGE_INTEGER

Jim Carrey 4. Okt 2016 16:46

AW: TWin32FindData: Dateigröße bestimmen
 
Stupide Frage :P
Ist es sinnvoll da wo es sinnvoll ist, UInt64 statt Int64 zu verwenden?
Habe immer ein bisschen Angst, dass wenn ich UInt64 verwende unvorhergesehen trotzdem ein Wert <0 rauskommt und es dann zu einer AV oder Ähnlichem kommt (da UInt64 deklariert statt Int64).

Luckie 4. Okt 2016 16:49

AW: TWin32FindData: Dateigröße bestimmen
 
Wenn eine Dateigröße negativ ist, dann stimmt an einer ganz anderen Stelle schon was nicht. :?

Jim Carrey 4. Okt 2016 16:53

AW: TWin32FindData: Dateigröße bestimmen
 
Das bedeutet, das kann eigentlich gar nicht passieren? Würde mich auch schwer wundern.

himitsu 4. Okt 2016 17:09

AW: TWin32FindData: Dateigröße bestimmen
 
Zitat:

Zitat von Jim Carrey (Beitrag 1349743)
Das bedeutet, das kann eigentlich gar nicht passieren? Würde mich auch schwer wundern.

UInt64 ist halt "richtiger", aber so lange die Dateien kleiner als 9,22 ExaByte sind, gibt es selten Probleme.

Aber früher gab es auch keine Probleme, wenn jemand Pointer zu Integer castete, dazumal damals schon Cardinal richtiger gewesen wäre, aber es jetzt ja eigentlich NativeUInt wäre.

jbg 4. Okt 2016 17:23

AW: TWin32FindData: Dateigröße bestimmen
 
Zitat:

Zitat von himitsu (Beitrag 1349746)
UInt64 ist halt "richtiger"

Ich habe wohl zu viel Java programmiert, da gibt es keine unsigned Datentypen.

Und durch die ganzen Cardinals im VirtualTreeView war man nur am Rum-casten, damit der Compiler keine "unsigned mit signed Integer-Vergleich" Warnungen ausspuckte. Deswegen verzichte ich normalerweise auf UInt64/Cardinal, wenn es sich nicht um interne Daten handelt, die von außen (andere Entwickler) zugegriffen werden, oder wenn ich am Schluss einen DWORD oder UINT WinAPI Parameter habe.

Jim Carrey 4. Okt 2016 17:44

AW: TWin32FindData: Dateigröße bestimmen
 
Zitat:

9,22 ExaByte
Da komme ich ja gerade mal so mit hin :-D
Spaß bei Seite. Bevor ich irgendwo Dateien mit einer Gesamtgröße von 9,22 EB habe, brauche ich tausende Euros, um die Festplatte dafür zu kaufen.

itsme 14. Apr 2020 13:01

AW: TWin32FindData: Dateigröße bestimmen
 
Hallo zusammen,

ich erlaube mir mal, den alten thread, nochmals in den Vordergrund zu holen.
TWin32FindData benutze ich um z.B. an Datum und Uhrzeit von Ordnern und Dateien zu kommen.
Funktioniert auch alles super, aber nicht auf einem x64 System, da stimmen Datum und Uhrzeit z. B. nicht!
Habe schon in die Hilfe geschaut und gegoogelt, konnte aber nicht finden wie man das von einem x86 Programm (Delphi XE) hin bekommt, damit auch x64 Daten korrekt erkannt werden.

Es wäre nett wenn jemand mir da einmal mit Rat zur Seite stehen könnte...

Danke und gleichzeitig wünsche ich euch allen nachträglich noch halbwegs schöne Ostern gehabt zu haben.

DieDolly 14. Apr 2020 13:27

AW: TWin32FindData: Dateigröße bestimmen
 
Versuch mal TDirectory.GetLastWriteTime(), TDirectory.GetLastAccessTime() und .GetCreationTime() für Verzeichnisse.
Dasselbe mit TFile für Dateien.

itsme 14. Apr 2020 14:24

AW: TWin32FindData: Dateigröße bestimmen
 
Vielen Dank, hat auf Anhieb super geklappt...

Hätte ich auch selbst darauf kommen können, hatte allerdings nicht in Erwägung gezogen, dass die Klassen so unterschiedlich agieren und rechnen.
Dachte Datum ist Datum und Uhrzeit ist Uhrzeit, so kann man daneben liegen. :o

Luckie 14. Apr 2020 18:43

AW: TWin32FindData: Dateigröße bestimmen
 
Auch wenn Itsme jetzt geholfen ist, hätte ich aus purer Neugier gewusst, wie man das Problem mit der API Funktion TWin32FindData löst bzw. Warum es nicht funktioniert.

himitsu 14. Apr 2020 20:57

AW: TWin32FindData: Dateigröße bestimmen
 
Ich hatte erst an den VirtualStore gedacht, aber dann wäre eher in 32 Bit der Fehler mit dem falschen Datum zu vermuten, wenn dort eine "andere" Datei nach der Redirection erwischt wird. :gruebel:
Außer der TE hatte schon das Problem und bekommt nun das "richtige" Datum, :stupid:
aber wir wissen ja nicht was es für Dateien sind, bzw. wo sie liegen.

itsme 15. Apr 2020 10:28

AW: TWin32FindData: Dateigröße bestimmen
 
Also ich hatte zunächst zum testen die Daten von LW:\Windows genommen, dieses Verzeichnis hat jeder, somit kann man gut vergleichen

Ich habe ein Win 7 32Bit auf separater Platte => K:\Windows
14.07.2009 02:37 wird über TWin32FindData korrekt gelesen

Zum Vergleich habe ich ein Win 8 64Bit auf anderer Platte => C:\Windows
22.08.2013 15:36
26.07.2012 05:37 wird aber über TWin32FindData ermittelt

Das ist so unterschiedlich, dass ich auch keine Erklärung dafür habe und nicht an TDirectory oder TFile gedacht hatte.
Datum sollte Datum und Uhrzeit Uhrzeit sein, ist aber wohl nicht so...

Dalai 15. Apr 2020 18:08

AW: TWin32FindData: Dateigröße bestimmen
 
Hast du mit deinem 32-bit Delphi-Programm irgendwelche Dateien in Unterverzeichnissen Windows\system32 getestet? Wenn ja, dann funkt die File-system redirection dazwischen und nach Windows\SysWOW64 umleitet.

Mit TWin32FindData hab ich bisher jedenfalls kein Problem gehabt.

Grüße
Dalai

itsme 16. Apr 2020 12:23

AW: TWin32FindData: Dateigröße bestimmen
 
Nein ich hatte nicht weiter getestet, sondern gleich umprogrammiert, habe das aber nachgeholt.
In der Tat ist es so das z.B. notepad.exe oder C:\ProgramData korrekt angezeigt werden.
Hingegen C:\Windows, C:\Windows\SysWOW64 oder C:\Benutzer nicht.

Es mag so sein wie du vermutet hast, allerdings muss ich jetzt nicht auf Biegen und Brechen herausfinden, warum das so ist.

Ich habe das Testprojekt mit TWin32Finddata jetzt aber gelöscht und kann keine weiteren Versuche mehr starten.
Wir wissen jetzt, dass es bei speziellen Ordnern so ist und können uns darauf einstellen.

himitsu 16. Apr 2020 14:17

AW: TWin32FindData: Dateigröße bestimmen
 
Hast du wirklich "C:\Benutzer" verwendet?

Hier wirs du viel Spaß haben,
denn C:\Users ist der richtige Name, dafür wurde eine Übersetzung definiert, damit der Explorer und die Speichen-/Öffnen-Dialoge es lokalisiert anzeigen,
und zusätzlich gibt es noch einen unsichtbaren Link, der Benutzer heißt und auf Users zeigt, für die, welche das eingeben, was der Explorer anzeigt.

Tja, und nun kommt der Spaß, denn da du hier den Link nicht auflöst, bekommst du das Datum des Links, anstatt des Ziels,
und scheinbar hat Windows hier teilweise eine automatische Auflösung drin, jenachdem ob die Dateisystemvirtualisierung des Programms aktiv ist. (für 32 Bit Programme in windows 64, wenn das Programm nicht als "aktuell" gekennzeichnet ist)

Der Explorer zeigt das Sichtbare an, aber übersetzt die Anzeige,
und APIs oder die Console verwenden die originalen Namen, auch von dem Unsichtbaren.

itsme 17. Apr 2020 12:13

AW: TWin32FindData: Dateigröße bestimmen
 
Ich habe sowohl C:\Users, als auch C:\Benutzer getestet... :lol:
Beides ging aber nicht.
Da ich vorher noch nicht mit TWin32FindData gearbeitet hatte, dachte ich, nimm mal zu Testzwecken C:\Windows, hat schließlich jeder.
Und alles andere hatte ich nur auf Frage von Dalai ausprobiert.

Habe natürlich mit meiner Wahl voll daneben gegriffen, aber wer konnte das ahnen.
Ist ja auch nur ein wenig Hobby-Programmieren und was ich machen wollte, habe ich letztendlich hin bekommen und wieder ein wenig hinzugelernt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:40 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