Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi FileStream.Size ist negativ (Datei größer als 2GB) (https://www.delphipraxis.net/42490-filestream-size-ist-negativ-datei-groesser-als-2gb.html)

endeffects 19. Mär 2005 16:47


FileStream.Size ist negativ (Datei größer als 2GB)
 
Hallo,

ich hab leider ein Problem beim Einlesen einer Datei (über 2GB) in einen FileStream,
wenn ich mit Hilfe von FileStream.Size die Größe des Streams ermittel möchte erhalte
ich einen negativen Wert. Reicht es diesen Wert in einen positiven umzuwandeln
oder muss eine andere Lösung erhalten?


MfG

Sharky 19. Mär 2005 16:49

Re: FileStream.Size ist negativ (Datei größer als 2GB)
 
Hai endeffects,

welche Delphi-Version hast Du denn?
Gab es nicht bis D7 diese beschränkung?

endeffects 19. Mär 2005 16:52

Re: FileStream.Size ist negativ (Datei größer als 2GB)
 
ich habe D7

Sharky 19. Mär 2005 17:55

Re: FileStream.Size ist negativ (Datei größer als 2GB)
 
Hmmm.... bei mir geht es ohne Fehler:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  blubb : TFileStream;
begin
  if (OpenDialog1.Execute) then
  begin
    blubb := TFileStream.Create(OpenDialog1.FileName,fmOpenRead);
    try
      ShowMessage (Format ('Dateigröße %d kB',[blubb.Size DIV 1024]));
    finally
      blubb.Free;
    end;
  end;
end;

Dax 19. Mär 2005 18:03

Re: FileStream.Size ist negativ (Datei größer als 2GB)
 
Schwierig.. speicherst du die Größe des Streams in einem Integer-Wert oder wird die as Integer-Wert verarbeitet? Wenn ja: unbedingt Int64 benutzen. Der generische signed-32Bit-Typ Integer geht nämlich nur bis 2^31-1 im positiven, also nur bis 2GB ;)

endeffects 19. Mär 2005 18:33

Re: FileStream.Size ist negativ (Datei größer als 2GB)
 
hallo,

das problem wird durch die abfrage von filestream.size erzeugt,
der wert ist ja nunmal leider nur ein longint.

Delphi-Quellcode:
SrcStream:=TFileStream.Create(FileName,fmOpenread or fmShareDenyNone);
N:=SrcStream.Size;
  while N>0 do
    ...
im fall von N<0 multipliziere ich den wert momentan einfach mit -1,
ich vermute allerdings dass das so nicht ganz richtig ist *g

NicoDE 19. Mär 2005 18:40

Re: FileStream.Size ist negativ (Datei größer als 2GB)
 
Zitat:

Zitat von endeffects
im fall von N<0 multipliziere ich den wert momentan einfach mit -1,
ich vermute allerdings dass das so nicht ganz richtig ist *g

Das wird spätestens bei $8000000 problematisch. Caste den Wert lieber auf einen vorzeichenlosen Typ gleicher Größe (Cardinal).

Sharky 19. Mär 2005 18:41

Re: FileStream.Size ist negativ (Datei größer als 2GB)
 
Zitat:

Zitat von endeffects
das problem wird durch die abfrage von filestream.size erzeugt,
der wert ist ja nunmal leider nur ein longint.
...

Also wenn ich mir den Code von TStream anschaue ist dort .Size als INT64 deklariert.

Binärbaum 19. Mär 2005 18:55

Re: FileStream.Size ist negativ (Datei größer als 2GB)
 
IMHO sollte es reichen, Size nach LongWord zu casten, damit können Werte bis 2^32-1 dargestellt werden (entspricht 4GB). Ansonsten sollte man Int64 verwenden (falls die Datei noch größer ist).
Hier mal eine Funktion, die den negativen Wert in die richtige Entsprechung umrechnet:
Delphi-Quellcode:
function RealeGroesse(aSize: LongInt): Longword;
begin
  if aSize>=0 then Result:= aSize
  else Result:= 2147483647 + (aSize+2147483648);
end;
MfG
Binärbaum

NicoDE 19. Mär 2005 19:03

Re: FileStream.Size ist negativ (Datei größer als 2GB)
 
Zitat:

Zitat von Binärbaum
Hier mal eine Funktion, die den negativen Wert in die richtige Entsprechung umrechnet

Man könnte das ganze kompatibler gestalten, indem man einen Int64 zurückgibt und eine überladene Funktion mit einem Int64 als Paramater schreibt (falls das Property von TFileStream in einer anderen Delphi-Version tatsächlich Int64 liefert...).

edit: ein Int64(Longword(aSize)) hätte es auch getan, die Additionen sorgen nur für Probleme bei aktivierten Overflow-Checks.

Delphi-Quellcode:
function HackIt(Size: Longint): Int64; overload;
{$IFDEF WIN32}
asm
        xor edx, edx
end;
{$ELSE}
begin
  Result := Longword(Size);
end;
{$ENDIF}

function HackIt(Size: Int64): Int64; overload;
{$IFDEF WIN32}
asm
  // fixme :)
end;
{$ELSE}
begin
  Result := Size;
end;
{$ENDIF}

Binärbaum 19. Mär 2005 19:31

Re: FileStream.Size ist negativ (Datei größer als 2GB)
 
Zitat:

Zitat von NicoDE
Zitat:

Zitat von Binärbaum
Hier mal eine Funktion, die den negativen Wert in die richtige Entsprechung umrechnet

Man könnte das ganze kompatibler gestalten, indem man einen Int64 zurückgibt und eine überladene Funktion mit einem Int64 als Paramater schreibt (falls das Property von TFileStream in einer anderen Delphi-Version tatsächlich Int64 liefert...).

edit: ein Int64(Longword(aSize)) hätte es auch getan, die Additionen sorgen nur für Probleme bei aktivierten Overflow-Checks.

Nunja, Int64 ist aber in der Hinsicht nicht ganz sinnvoll, da ein Int64 ja auch negative Werte annehmen kann, aber es keine Dateien gibt, die eine negative Größe haben. Int64 ist wie gesagt nur dann nötig, wenn die Datei größer als 4GB ist, ansonsten reicht Longword. (AFAIK können Dateien unter Win9x/ME und WinNT nicht größer als 4GB sein, wie das bei WinXP aussieht, weiß ich nicht :? )
Und wegen dem Overflow: der sollte eigentlich nicht auftreten, denn wenn man zu einem negativen Wert 2 Mrd. addiert, ist man immer noch unter 2 Mrd. und somit auch noch im Bereich von LongInt.
Notfalls kann die Zeile ja so abgeändert werden:
Delphi-Quellcode:
  else Result:= 2147483647 + LongWord(aSize+2147483648);
Damit ist man dann auf der sicheren Seite.

MfG
Binärbaum

NicoDE 19. Mär 2005 19:47

Re: FileStream.Size ist negativ (Datei größer als 2GB)
 
Zitat:

Zitat von Binärbaum
Nunja, Int64 ist aber in der Hinsicht nicht ganz sinnvoll, da ein Int64 ja auch negative Werte annehmen kann, aber es keine Dateien gibt, die eine negative Größe haben. Int64 ist wie gesagt nur dann nötig, wenn die Datei größer als 4GB ist, ansonsten reicht Longword. (AFAIK können Dateien unter Win9x/ME und WinNT nicht größer als 4GB sein, wie das bei WinXP aussieht, weiß ich nicht :? )

Das High-Bit (wieviele TB bzw. PB sind das?) wird AFAIK von Windows ohnehin nicht interstützt. Und Delphi32 hat nunmal keinen UInt64 :)

Union 20. Mär 2005 11:57

Re: FileStream.Size ist negativ (Datei größer als 2GB)
 
Zitat:

Zitat von endeffects
Hallo,
ich hab leider ein Problem beim Einlesen einer Datei (über 2GB) in einen FileStream,
wenn ich mit Hilfe von FileStream.Size die Größe des Streams ermittel möchte erhalte
ich einen negativen Wert. Reicht es diesen Wert in einen positiven umzuwandeln
oder muss eine andere Lösung erhalten?
MfG

In welchem Kontext tritt Dein "Fehler" auf? Mit D7 funktioniert es auf jeden Fall:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
   Stream : TFileStream;
begin
   Stream := TFileStream.Create('e:\tlinux4\base.img', fmOpenRead);
   ShowMessage(Format('Filesize %s: %d', ['base.img', Stream.Size]));
   Stream.Free;
end;
Ausgabe:
Code:
---------------------------
Project1
---------------------------
Filesize base.img: 4278190080
---------------------------
OK  
---------------------------
Ansonsten hier eine Funktion zur Rückgabe der Größe einer beliebigen Datei:
Delphi-Quellcode:
function DiskFileSize(FileName : string) : int64;
var
   handle   : THandle;
   findData : TWin32FindData;
begin
   Result := -1;

   handle := FindFirstFile( PChar( FileName ), findData );
   if ( handle <> INVALID_HANDLE_VALUE ) then
   begin
      Windows.FindClose( handle );

      if ( ( FindData.dwFileAttributes AND FILE_ATTRIBUTE_DIRECTORY ) = 0 ) then
      begin
         Result := (findData.nFileSizeHigh * MAXDWORD)+ findData.nFileSizeLow;
      end;
   end;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:09 Uhr.

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