Entwickler-Ecke

Dateizugriff - Verarbeiten von großen Dateien (> 2GB bzw. > 4GB)


nocki - Fr 19.03.10 13:48
Titel: Verarbeiten von großen Dateien (> 2GB bzw. > 4GB)
Hallo,

ich bin neu in diesem Forum und habe nur mäßige Delphi-Kenntnisse.
Vielleicht kann mir einer der Experten bei der Lösung meines Problems helfen (ich arbeite mit Delphi 7 unter Win XP):

Nach meiner Kenntnis kann ich mit Delphi7 nur Dateien verarbeiten, die kleiner als 2 GB sind, da seek und FilePos jeweils mit 32-bit-Integers (longint) arbeiten. Ich möchte aber Dateien verarbeiten, die größer als 2 GB sind.
- Gibt es Routinen, welche die 32 bit ganz ausnutzen (also mit vorzeichenlosen Integers arbeiten) und damit Dateigrößen bis 4 GB erlauben?
- Gibt es evtl. sogar Routinen, die mit 64-bit-Integers arbeiten und damit sogar Dateien >4 GB verarbeiten können?

Vielen Dank für Eure Hilfe

nocki


Martok - Fr 19.03.10 14:24

user profile iconnocki hat folgendes geschrieben Zum zitierten Posting springen:
Hallo,

:welcome: im Forum!

user profile iconnocki hat folgendes geschrieben Zum zitierten Posting springen:
Nach meiner Kenntnis kann ich mit Delphi7 nur Dateien verarbeiten, die kleiner als 2 GB sind, da seek und FilePos jeweils mit 32-bit-Integers (longint) arbeiten.

Not true.
TFileStream kann seit Delphi 4(?) mit int64 umgehen, damit wäre das also dein zweiter Fall.

Auch die WinAPI-Wrapper FileSeek, FileWrite, FileRead etc. existieren in überladenen Versionen, die int64 verwenden.
Was Borland nicht gemacht hat: GetFileSize einen solchen Wrapper verpassen. Da müss man selber was schrauben.

Aber wie gesagt: TStream kann das, also kein Grund da unnötigen Aufwand zu betreiben ;)

cu
Martok


nocki - Fr 19.03.10 14:54

Vielen Dank für die schnelle Hilfe,

dieser Hinweis war sehr hilfreich. Ich wußte nicht, daß es solche Routinen mit int64 bereits seit langer Zeit gibt und werde es nun mit TFilestream probieren.

Gruß Nocki


kurt59 - Fr 19.03.10 18:14

Zum Testen wurde eine Datei mit 6GB geöffnet und dann versucht
den Dateizeiger auf eine Position >2GB zu setzen.
Bei Delphi 5 kommt mit fstream.position:=4300000000 eine Fehlermeldung:
Exception der Klasse ERangeError 'Fehler bei Bereichsüberprüfung'
Das war's - bis 2GB geht es.

Kurt


Martok - Fr 19.03.10 18:29

Ah, okay. Dann war mein (?) oben doch berechtigt, und die Änderung wohl erst in D6 oder D7 passiert.

Danke fürs erforschen ;)


Xentar - Fr 19.03.10 18:45

Grad nachgesehen: Position ist unter D5 noch ein Longint, also max. 4 GB.


kurt59 - Fr 19.03.10 20:35

Position ist unter D5 ein Longint - max. 2 GB.


Martok - Fr 19.03.10 20:42

Position ist unter D5 ein signed Longint - max. 2 GB.

:lol:


nocki - Mo 22.03.10 12:55

Hallo,

ich habe (unter D7, WinXP) mal eine 5-GB-Datei erzeugt und dann versucht, sie mittels TFilestream zu lesen. Bis zur 2GB-Grenze klappt alles, dann nicht mehr:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
procedure TForm1.Button2Click(Sender: TObject);
var
  f:         TFileStream;
  p,p1:      int64;
const
  GB2m1:int64=2*int64(1024)*1024*1024-1;
  GB2  :int64=2*int64(1024)*1024*1024;
  GB2p1:int64=2*int64(1024)*1024*1024+1;
begin
  f :=TFileStream.Create('d:\Test',fmOpenRead);
  p:=-2; p1:=-2;
  p:=f.Seek(GB2m1,soFromBeginning);  p1:=f.Position;
  MessageDlg('p,p1='+inttostr(p)+','+inttostr(p1), mtInformation, [mbOk], 0);
  p:=-2; p1:=-2;
  p:=f.Seek(GB2,soFromBeginning);    p1:=f.Position;
  MessageDlg('p,p1='+inttostr(p)+','+inttostr(p1), mtInformation, [mbOk], 0);
  p:=-2; p1:=-2;
  p:=f.Seek(GB2p1,soFromBeginning);  p1:=f.Position;
  MessageDlg('p,p1='+inttostr(p)+','+inttostr(p1), mtInformation, [mbOk], 0);
  f.Free;
end;


Das erste seek liefert die erwarteten Werte: 2147483647,2147483647.
Die nächsten beiden seeks liefern jedoch -1,2147483647.
Wo liegt der Fehler?

nocki

Moderiert von user profile iconGausi: Delphi-Tags hinzugefügt


BenBE - Mo 22.03.10 19:41

Wenn Du derlei große Dateien via 32 Bit machen willst, solltest Du mal soCurrent probieren. (Sprung relativ zur aktuellen Position). Beachte, dass die angegebenen Offsets wahrscheinlich nicht stimmen werden.


nocki - Fr 26.03.10 15:26

Danke für den Tipp, BenBE.

ich hab es mal mit soCurrent probiert - das klappt tatsächlich, wenn man nur max. 2 GB weite Sprünge macht.

Viel besser ist aber die Benutzung von TFilestream.Position. Einfach Position einen neuen Wert zuweisen, dann read aufrufen - fertig.

Auf das Einfachste kommt man eben zuletzt.

Vielen Dank für alle Hinweise

nocki