Autor Beitrag
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Do 28.04.05 22:14 
512 Bytes ist genau ein logischer Sektor auf der Festplatte (ein physikalischer Sektor sind 520 IIRC), aber Windows liest generell ganze Sektoren von der Festplatte. Wenn Du also immer 512 Bytes (oder Vielfache) liest, bleibst Du immer genau am Anfang eines Sektors und Windows muss die Lesezugriffe nicht aufspalten, d.h. weniger Lesezugriffe --> Schnellerer Zugriff.

@Puffer: String[1024] kann nicht gehen, da es einen ShortString definieren würde und diese sind auf 256 Bytes begrenzt.

Definiere statt dessen einen ReadedString: Array [0..1023of Char, Basisindex ist dann Index 0.

BTW: Es müsste eigentlic ReadString heißen, da Read in allen drei Formen gleich bleibt.

_________________
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.
Heiko
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: Fr 29.04.05 19:59 
Wie soll ich das realisieren das er gleich 512 Bytes ausliest?

Den Quelltext von jasocoul versteh ich irgendwie nicht ganz. Was bedeutet zum Beispiel seek? Und warum ist seine Variante schneller? Er liest die Bytes auch ja einzel aus. Oder sollte ich es lieber mit TFileStream versuchen?
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Fr 29.04.05 20:15 
user profile iconHeiko hat folgendes geschrieben:
Wie soll ich das realisieren das er gleich 512 Bytes ausliest?

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure ReadBytesFast;
var
    Puffer: array[0..1023of byte;
    F: File;
begin
    {... Datei öffnen und so ... }
    BlockRead(F, Puffer[0], 1024);
    {... Datei schließen und so ... }
end;


user profile iconHeiko hat folgendes geschrieben:
Den Quelltext von jasocoul versteh ich irgendwie nicht ganz.
Ist auch eine schlechte Angewohnheit in meinen Augen, mit den TP-Befehlen für IO unter Delphi zu arbeiten.

Er hat nur ähnlich wie ich jetzt oben, die Open- und Close-Dinge für Dateizugriff weggelassen. Ansonsten ist seine Variante mit deiner letzten ähnlich.

user profile iconHeiko hat folgendes geschrieben:
Was bedeutet zum Beispiel seek?

Die DOH ist dein bester Freund: Seek (von engl. Suchen) springt in einer Datei an eine andere Position.

user profile iconHeiko hat folgendes geschrieben:
Und warum ist seine Variante schneller? Er liest die Bytes auch ja einzel aus.

Ist se nicht, hab ich in meinem vorigen Posting erklärt ... er liest ein Byte pro Dateizugriff und hat dadurch sehr viel Verwaltungsaufwand seitens des OS, während das Lesen ganzer Blöcke wesentlich schneller geht.

user profile iconHeiko hat folgendes geschrieben:
Oder sollte ich es lieber mit TFileStream versuchen?

Jip. das ist von der Logik und der Implementierung einfacher (und zeitgemäßer). Geht etwa so hier:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
procedure ReadBytesFastByFileStream;
var
    Puffer: array[0..1023of byte;
    FS: TFileStream;
begin
    FS := TFileStream.Create('C:\Datei.dat', fmOpenRead or fmShareDenyWrite);
    try
        FS.ReadBuffer(Puffer[0], 1024);
    finally
        FreeAndNil(FS);
    end;
end;


Mit FS.Position kannst Du die Position ändern (oder FS.Seek direkt aufrufen)

_________________
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.
Heiko
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: Fr 29.04.05 20:20 
Normalerweise arbeite ich ja mit TFileStream. Es gab nur einen Grund warum ich ihn hier nicht verwendet hatte. Gibt es dort z.B. den Befehl eof? Und ich habe es auch nicht verwendet, da ich sonst immer nur bekannte Formate auslese, und nicht unbekannte.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Fr 29.04.05 20:24 
Direkt als Abfrage gibt es in Streams den EOF-Befehl nicht, aber Du kannst Dir mit FS.Position >= FS.Size den EOF-Befehl ganz leicht nachbauen.

_________________
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.
Heiko
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: Fr 29.04.05 20:26 
Und ist es egal ob ich FileStream.Free nehme oder FreeAndNil(FileStream)?

Und woran erkenne ich wieviel Bytes im letzten Sektor für mich wirklich von Bedeutung sind? Denn es kann ja sein, dass ich nur 10 Bytes vom letzten Sektor benötige. Oder muss ich das mit modulo selber herausfinden?
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Fr 29.04.05 20:32 
user profile iconHeiko hat folgendes geschrieben:
Und ist es egal ob ich FileStream.Free nehme oder FreeAndNil(FileStream)?

Eigentlich ja, es gibt nur einen bedeutenden Vorteil von FreeAndNil: Die Referenz auf das Objekt wird auch gleich gelöscht, womit der Aufruf von Assigned korrekt False ergibt. Das Manuelle auf Nil setzen entfällt somit.

user profile iconHeiko hat folgendes geschrieben:
Und woran erkenne ich wieviel Bytes im letzten Sektor für mich wirklich von Bedeutung sind? Denn es kann ja sein, dass ich nur 10 Bytes vom letzten Sektor benötige. Oder muss ich das mit modulo selber herausfinden?
Nein, brauchst Du nicht.

Wenn Du mit FS.Read anstatt mit FS.ReadBuffer arbeitest, werden nur soviele Bytes zurückgegeben, wie tatsächlich vorhanden sind. Dass nur 10 Bytes gelesen wurden, gibt die Funktion dann als Result zurück.
ausblenden Delphi-Quelltext
1:
ReadSize := FS.Read(Puffer[0], 512);					

Der Rest (ab dem 11. Byte) ist dann aber undefiniert.

_________________
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.
Heiko
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: Sa 30.04.05 10:20 
thx,

das Auslesen braucht jetzt mit FileStream nur halbe Sekunde, anstatt 10 Minuten mit der alten Variante :shock: .
Heiko
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: Sa 30.04.05 10:39 
Für 523 MB braucht meiner nur 15 Sekunden :shock: !! Ich möcte nicht wissen, wie lange der mit meiner ertsne Variante gebraucht hätte. Eine Woche? Spielt jetzt aber keine Rolle mehr.

Aso es scheint egal zu sein, ob man nun 1024 oder 2048 mit einmal ausliest. Man macht kein sichtbaren Gewinn mehr. Es lohnt sich aber statt 512 1024 zu nehmen.
Heiko
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: Mo 02.05.05 17:08 
Also irgendwie liest der nicht das ein was ich will :gruebel: :
ausblenden Quelltext
1:
2:
3:
NY@ÞÏk|ž+ñ–‚+£fûËœh—èR@#: ÏQ™uÊ
­ßåúíhþ¯ÓÜ/aÁ©éjíá&M±^êØio¶ˆ*¾Í»[é¾%(ÙJ­eDؘað?ÏÂ’$œ‰—
{ßErÝGŠëÀ…"gØ4lö·îP8Ë´I¿p‹l=œ"¬t²“1lMQ[oçb÷ßÁz‘¨È…ñ'‡¡¼}? 5ç 9âLnýwÒè>Ù”„¯


Das sollte eigentlich alle 256 ASCII-Code-Zeichen sein. Ich glaube nicht, dass die das sind.

Hier der Quelltext:
ausblenden volle Höhe 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:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
procedure Kompression(const DateiFileStream: TFileStream; FileStr: String);
var i: Cardinal;
    SignCounter: array[0..255of Cardinal;
    ReadBuffer: array[0..511of Byte;
    ReadSize: Word;
    TakeSign: array of Byte;
//    DateiFile: File of Byte;
    KompFileStream: TfileStream;
begin
 for i:=0 to 255 do
  begin
   SignCounter[i]:=0;
  end;
 while DateiFileStream.Position<DateiFileStream.Size do
  begin
   ReadSize:=DateiFileStream.Read(ReadBuffer[0], 512);
   for i:=0 to ReadSize-1 do
    begin
     inc(SignCounter[ReadBuffer[i]])
    end
  end;
// AssignFile(DateiFile, Copy(FileStr, 1, length(FileStr)-length(ExtractFileExt(FileStr)))+'.pck');
 KompFileStream:=TFileStream.Create(Copy(FileStr, 1, length(FileStr)-length(ExtractFileExt(FileStr)))+'.pck', fmCreate or fmOpenWrite or fmShareDenyWrite);
// Rewrite(DateiFile);
 for i:=0 to 255 do
  begin
   if SignCounter[i]>0 then
    begin
     SetLength(TakeSign, High(TakeSign)+2);
     TakeSign[High(TakeSign)]:=SignCounter[i];
     KompFileStream.WriteBuffer(SignCounter[i], 1)
//     Write(DateiFile, SignCounter[i]);
    end
  end;
// CloseFile(DateiFile);
 FreeAndNil(KompFileStream);
end;

procedure TForm1.Button1Click(Sender: TObject);
var DateiFileStream: TFileStream;
    OpenDialog: TOpenDialog;
begin
 OpenDialog:=TOpenDialog.Create(Self);
 if OpenDialog.Execute then
  begin
   DateiFileStream:=TFileStream.Create(OpenDialog.FileName, fmOpenRead or fmShareDenyWrite);
   if DateiFileStream.Size<=4294967295 then
    begin
     Kompression(DateiFileStream, OpenDialog.FileName);
    end
   else
    begin
     Application.MessageBox('Die ausgewählte Datei ist für diese Version zu groß!''Datei zu Groß'16)
    end;
   FreeAndNil(DateiFileStream);
  end
end;
Heiko
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: Di 03.05.05 10:56 
Ok ich habe den Fehler gefunden. Hier die Lösung.
KidPaddle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 351

WinXP,Linux
D7 Prof, XE7
BeitragVerfasst: Di 03.05.05 12:57 
Ich würde den Code wie folgt ändern. Der Code könnte noch optimiert und eine verbesserte Fehlerprüfung müßte noch eingebaut werden.

ausblenden volle Höhe 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:
31:
32:
33:
34:
35:
36:
37:
38:
39:
procedure TForm1.Button1Click(Sender: TObject);
var DateiFile: TextFile;
    ReadedString: array[0..1023of Byte; <--- Datentyp geaendert
    iBytesRead : Integer;
    ReadedByte: Byte; <---- Neu
    i, j: Cardinal;
    SignCounter: array[0..255of 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
     iBytesRead := Read(DateiFile, ReadedString); // Wieviele Zeichen wurden gelesen
     if (iBytesRead > 0then // <-- Es wurden Daten gelesen
      begin
       for j:= 0 to (iBytesRead - 1do
        begin
         ReadedByte:=ReadedString[j];
         inc(SignCounter[ReadedByte])
        end
      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;


Gruß
KidPaddle