| Autor |
Beitrag |
cht
Hält's aus hier
Beiträge: 9
Win 98 SE, Win XP
D6 Prof
|
Verfasst: So 08.08.04 12:43
Hallo Leute,
Ich bin auf der Suche nach einer Möglichkeit, möglichst schnell einzelne Bytes aus einer Datei auszulesen. Im Moment lade ich die ganze Datei in einen TMemoryStream, um dann per Seek und ReadBuffer darauf zuzugreifen. Für größere Dateien ist das natürlich nicht sehr schön. Also direkt von der Datei lesen - nur wie? nehme ich einen TFileStream, den Pascal-Typ file oder die Win-API-Routinen? Es geht in erster Linie um die Geschwindigkeit, denn wenn ich bei jedem Seek-Read-Vorgang sagen wir 30µs spare, macht das bei einer 2 MB-Datei schon 1 Minute!
Danke für eure Hilfe
mfG
cht
|
|
maxk
      
Beiträge: 1696
Erhaltene Danke: 1
Win XP, Debian Lenny
Delphi 6 Personal
|
Verfasst: So 08.08.04 16:30
Ich verwende gerne Streams, daher kann ich dir TFileStream nur ans Herz legen.
_________________ Ein Computer wird das tun, was Du programmierst - nicht das, was Du willst.
|
|
cht 
Hält's aus hier
Beiträge: 9
Win 98 SE, Win XP
D6 Prof
|
Verfasst: So 08.08.04 17:43
warum benutzt du die denn gerne? nur weil sie einfacher zu proggen sind? ich mach nämlich gerne etwas mehr aufwand um mehr geschwindigkeit rauszuholen.
Danke für deine Antwort
cht
|
|
maxk
      
Beiträge: 1696
Erhaltene Danke: 1
Win XP, Debian Lenny
Delphi 6 Personal
|
Verfasst: So 08.08.04 17:47
Ich habe es mal ausprobiert, und da ware der FileStream sehr viel schneller als die TP-Variante. Mit den APIs habe ich es (aus Faulheit) noch nicht probiert. Ich habe aus einer 1 GB Datei ab 500 MB, 500 KB ausgelesen.
_________________ Ein Computer wird das tun, was Du programmierst - nicht das, was Du willst.
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: So 08.08.04 20:18
Also wenn du immer nur einzelne Bytes liest wirst du von der Geschwindigkeit her immer recht niedrig bleiben... warum nicht einen größeren Puffer einlesen und den dann abarbeiten..?
Möglicherweise wären in deinem Fall aber auch MMFs (Memory Mapped Files) angebracht... (weiß ja nicht genau was du vor hast)
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mo 09.08.04 22:24
Was er vor hat, würde mich aber auch mal interessieren...
Aber erstmal generell:
KEINE EINZELNEN Bytes lesen, sondern immer Blöcke = x * 512 Bytes (bevorzugt: 1024, 4096, 65536 Bytes).
TMemoryStream bei Files: NO!,
File-I\O-API: Vermeiden, soviel mehr Performance gibt's dabei nicht, Streams reichen schon
@MMFs: Schnellste Möglichkeit, ABER gute Pointer-Kenntnisse sind Voraussetzung, sonst gibt's Endlose AV-Ansammlungen.
Für einzelne Bytes würd ich in seinem Fall mal so tippen, dass sich TFileStream mit einem 64KB Puffer anbietet.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
supermuckl
Hält's aus hier
Beiträge: 3
Win2k3, WinXP,Mandrake10
D6 Ent, K3 Ent
|
Verfasst: Sa 14.08.04 23:51
| Zitat: | | ABER gute Pointer-Kenntnisse sind Voraussetzung, sonst gibt's Endlose AV-Ansammlungen |
was bitte sind AV-Ansammlungen?
hab ne komponente geschrieben die MMF benutzt und würde gerne wissen ob ich da was übersehen hab was probleme machen könnte
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: So 15.08.04 00:25
| supermuckl hat folgendes geschrieben: | | Zitat: | | ABER gute Pointer-Kenntnisse sind Voraussetzung, sonst gibt's Endlose AV-Ansammlungen | was bitte sind AV-Ansammlungen? |
AV ist ne Abkürzung, die für AccessViolation (Zugriffsverletzung) steht.
Naja, und Ansammlungen davon sind diese endlosen Haufen von Meldungen, die du daraufhin kriegst
Ohne Source gestaltet sich die Fehlersuche etwas kompliziert 
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
supermuckl
Hält's aus hier
Beiträge: 3
Win2k3, WinXP,Mandrake10
D6 Ent, K3 Ent
|
Verfasst: So 15.08.04 21:53
ähm ne ich hab keine fehler.. aber ich will ja nicht das welche kommen  deshalb dachte ich hättest du für mich nen tip worauf ich besonderst achten sollte..
AV kommen ja dann wohl wenn ich auf einen speicherbereich zugreife den es nicht gibt ( z.b. länger als das MMF View ist )
sowas hab ich schon von vornherein ausgeschlossen..
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: So 15.08.04 22:49
| supermuckl hat folgendes geschrieben: | ähm ne ich hab keine fehler.. aber ich will ja nicht das welche kommen deshalb dachte ich hättest du für mich nen tip worauf ich besonderst achten sollte.. |
Direkte Sachen, worauf man achten sollte nicht, aber ne Empfehlung:
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| type TByteArray = array [0..0] of Byte: PByteArray = ^TByteArray;
var PBA:PByteArray;
@PBA := MMFData; |
Zugriff auf die Einzelbytes dann mit:
PBA^[0..MMFSize-1] (Lesen und Schreiben, Dach nach Bezeichner und Vor Index-Klammer beachten!)
Moderiert von Klabautermann: Delphi-Tags hinzugefügt.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Net-Spider
      
Beiträge: 21
|
Verfasst: Do 16.09.04 13:42
dazu habe ich auch gleich eine frage, ich möchte auch einzelne bytes lesen, ein puffer nützt mir nicht viel, weil ich 4bytes lese und aus den ergebnissen mir die nächste lesestelle errechne.
was wäre dafür die beste möglichkeit, es handelt sich dabei um ein paar dateien mit 3mb-5mb pro datei bei rund 4*10000 lesevorgängen oder anders gesagt will ich ca. alle 400 bytes 4 bytes lesen
|
|
jasocul
      
Beiträge: 6395
Erhaltene Danke: 149
Windows 7 + Windows 10
Sydney Prof + CE
|
Verfasst: Do 16.09.04 13:53
Den folgenden Tip habe ich nicht getestet, aber das müsste eigentlich funktionieren:
Definiere die Datei-Variable einfach als typisierte Datei (File of Byte). Besser vielleicht File of Array[0..3] of Byte, da Du ja immer 4 Byte einliest. Das hängt aber davon ab, ob die Daten-"länge", die dazwischen stehen, auch immer durch 4 teilbar sind.
Danach benutzt Du die Seek-Prozedur. Damit kannst Du dann direkt eine Stelle in der Datei "anspringen".
|
|
Net-Spider
      
Beiträge: 21
|
Verfasst: Do 16.09.04 14:00
schonmal danke für die schnelle antwort, aber ich weiß immer nicht WIE ich die datei öffnen soll, mir geistert da immer openfile, fileopen, appendfile im kopf rum aber das scheinen nicht die richtigen zu sein, zumindest laut delphi hilfe
|
|
jasocul
      
Beiträge: 6395
Erhaltene Danke: 149
Windows 7 + Windows 10
Sydney Prof + CE
|
Verfasst: Do 16.09.04 14:29
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| procedure Dateilesen; var f : file of byte; b4 : Array [0..3] of byte; cnt : Integer; Position : LongInt; begin Assign(f, 'C:\TEST.TXT'); Reset(f); for cnt := 0 to 3 do read(f, b4[cnt]); seek(f, Position); Close(f); end; |
Falls noch Fragen sind, denn sach bescheid.
|
|
grayfox
      
Beiträge: 800
win98, winXP
D4 Standard; D6 Personal
|
Verfasst: Do 16.09.04 14:43
und ich dachte immer, dass man mit 'AssignFile' das file öffnet & mit 'CloseFile' wieder schliesst 
|
|
jasocul
      
Beiträge: 6395
Erhaltene Danke: 149
Windows 7 + Windows 10
Sydney Prof + CE
|
Verfasst: Do 16.09.04 14:47
Ich meine, dass das für Text-Files vorgesehen ist. Oder war es um Verwechselungen mit dem Assign-Befehl zu vermeiden? 
|
|
Net-Spider
      
Beiträge: 21
|
Verfasst: Do 16.09.04 15:01
ah, danke, das hilft mir weiter, nun kann ich die mp3dateien weiter einlesen (nicht ID3-Tags)
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Do 16.09.04 18:31
Stimmt so nicht:
AssignFile initialisiert den MBC, der von Delphi verwendet wird, um die Datei anzusprechen.
Direkt geöffnet wird die Datei erst durch Reset, Append und Rewrite.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
jasocul
      
Beiträge: 6395
Erhaltene Danke: 149
Windows 7 + Windows 10
Sydney Prof + CE
|
Verfasst: Do 16.09.04 19:01
@BenBE
Da habe ich wohl zu hastig gelesen. Du hast natürlich Recht. Mit AssignFile werden die Dateien natürlich nicht geöffnet.
|
|
Heiko
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: Do 28.04.05 09:45
Habe ich euch richtig verstanden, dass TFileStream schneller ist als die Variante von jasocoul mit AssignFile, ...?
Ich habe es erstmal mit diese Variante hier probiert:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:
| procedure TForm1.Button1Click(Sender: TObject); var DateiFile: TextFile; ReadedByte: Byte; i, j: Cardinal; SignCounter: array[0..255] of Cardinal; begin if GetFileSizeEx('WMEncoder.exe')<=4294967295 then begin for i:=0 to 255 do begin SignCounter[i]:=0; end; AssignFile(DateiFile, 'WMEncoder.exe'); Reset(DateiFile); while not eof(DateiFile) do begin Read(DateiFile, ReadedByte); inc(SignCounter[ReadedByte]) end; CloseFile(DateiFile); for i:=0 to 255 do begin ShowMessage(IntToStr(i)+': '+IntToStr(SignCounter[i])); end; end else begin Application.MessageBox('Die ausgewählte Datei ist für diese Version zu groß!', 'Datei zu Groß', 16) end; end; |
Diese Variante ist aber wirklich sehr langsam. Da ich dann dieses Thema hier mir durchgelesen hatte, habe ich mal folgende Variante probiert:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35:
| procedure TForm1.Button1Click(Sender: TObject); var DateiFile: TextFile; ReadedString: Strings[1024]; ReadedByte: Byte; i, j: Cardinal; SignCounter: array[0..255] of Cardinal; begin if GetFileSizeEx('WMEncoder.exe')<=4294967295 then begin for i:=0 to 255 do begin SignCounter[i]:=0; end; AssignFile(DateiFile, 'WMEncoder.exe'); Reset(DateiFile); while not eof(DateiFile) do begin Read(DateiFile, ReadedString); for j:=1 to length(ReadedString)+1 do begin ReadedByte:=Ord(ReadedString[j]); inc(SignCounter[ReadedByte]) end end; CloseFile(DateiFile); for i:=0 to 255 do begin ShowMessage(IntToStr(i)+': '+IntToStr(SignCounter[i])); end; end else begin Application.MessageBox('Die ausgewählte Datei ist für diese Version zu groß!', 'Datei zu Groß', 16) end; end; |
Ich bekomme aber immer Fehlermeldungen. Wie mancht ihr es dann (also k*512 Bytes auslesen)?
Und warum sollte man gerade k*512 Bytes auslesen?
|
|
|