Autor Beitrag
hRb
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 209
Erhaltene Danke: 12



BeitragVerfasst: Do 26.03.20 17:15 
Hallo zusammen,
die Frage zum "Optimalen" Lesen beliebiger Dateien blieb 12 Tage ohne Antwort. Ich zergliedere meine Frage neu, weil ich beim Realisieren meiner Aufgabe auf zwei Syntax-Probleme gestoßen bin, bei der ich Hilfe benötige. Aufgabe lautet nach wie vor: Einlesen einer beliebigen Datei ins Memory und Daten in Hexaform darstellen. Lade hierzu die Datei in einen MemoryStream. Habe dazu folgende Funktion geschrieben, die mich jedoch in mehreren Punkten nicht befriedigt:
1. Kann FiStream nicht mit der Option fmOpenRead or fmShareDenyNone einlesen. Dies führt bei schon geöffneter Datei zu error.
2. MemoryStream ist ein Pointer. Ich dachte hiermit auf die Daten direkt zugreifen zu können. Habe Syntax-Problem mit Pointer! (Über die Read-Funktion mit einem weiteren Buffer funktioniert mein Programm. (wäre aber ein weiteres Umspeichern der Daten). Wie greife ich auf die Daten von MemoryStrem direkt zu?
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:
Function ReadFi(FileName:string):boolean;
var
  Buffer: TBytes;
  FiStream : TMemoryStream;
  j: int64;
  s: string;
begin
  try
    s:='';
//   FiStream:=TMemoryStream.Create(FileName, fmOpenRead or fmShareDenyNone); //funktioniert nicht, daher der Umweg über Zeile 11+12
    FiStream := TMemoryStream.Create;
    FiStream.LoadFromFile(FileName); // Load stream, Funktion erlaubt jedoch nicht  fmOpenRead or fmShareDenyNone
    FiStream.Position := 0;          // Reset to stream-start.
//    for j:=1 to 50 {FiStream.Size} do
//      s:= s + IntToHex(ord(FiStream.Memory^.[j]),2) + ' ';  //Syntax-Fehler: Memory^.[j] wie richtig?
    SetLength(Buffer, FiStream.Size);
    FiStream.ReadBuffer(Pointer(Buffer)^, FiStream.Size);
    for j:=0 to 50 {FiStream.Size} do
//Bearbeitung wurde hier auf 50 Zeichen zum Test verkürzt, später Hexa-Zeilen 
      s:= s + IntToHex(ord(Buffer[j]),2) + ' ';
      Form1.RichEdit1.Lines.Add(s);
  except
    on Exception do begin
      FiStream.Free;
      Result:=False;
      exit;
    end;
  end;
  FiStream.Free;
  Result:=true;
end;
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4298
Erhaltene Danke: 925

Win10
C#, C++ (VS 2015/17)
BeitragVerfasst: Do 26.03.20 18:08 
Warum benutzt du hier überhaupt einen TMemoryStream und nicht gleich einen TFileStream?
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8480
Erhaltene Danke: 447

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Do 26.03.20 18:46 
Grade bei sehr, sehr großen Daten wird der Ansatz mit MemoryStream nicht mehr funktionieren, denke ich. Soweit ich weiß, lädt LoadFromFile die gesamte Datei in den Speicher - und bei 32-Bit-Anwendungen ist dann in der Regel irgendwo zwischen 1 und 2GB Schluss.

Daher: Mit FilesStream arbeiten, die Daten häppchenweise in den Buffer laden, verarbeiten, und dann den nächsten Teil laden.

Aber zu deiner Frage direkt: Das sollte so gehen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
var ms: TMemoryStream;
  p: ^Byte;
  b: Byte;
  i: Integer;
// ...
p := ms.Memory;
for i := 0 to 100 do
begin
  b := p^;
  Memo1.Lines.Add(IntToStr(b));
  inc(p);
end;

_________________
We are, we were and will not be.
hRb Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 209
Erhaltene Danke: 12



BeitragVerfasst: Do 26.03.20 20:44 
Zunächst Danke,
damit der Hintergrund meiner Frage besser erkennbar wird: Ich habe eine ganze Reihe von Speichersticks und Festplatten mit Sicherungskopien von Dateien, genauer gesagt auch ganze Ordner. Hier gibt es Textdateien aber auch andere Typen. Diese möchte ich auf Byteebene zu vergleichen. Einmal komplette Ordner, aber auch gezielt zwei Einzeldateien. Ein Vergleichsprogramm das auf Filename, Datum und Dateilänge vergleicht habe ich schon. Eigenartigerweise finde ich jedoch auch namensgleiche Dateien, die genau eine Stunde Differenzzeit aufweisen. Nun wollte ich mir ein eigenes Vergleichsprogramm schaffen. Gedacht war schon, dass ich immer Teilblöcke von 4096 Byte vergleiche und die Anzeige erst beim beim ersten Unterschied aktiviere.
Ich habe ein solches Programm mit Delphi 7 schon (mit einer schrecklichen Oberfläche). Ist auch viel zu langsam und knallt bei großen Dateien (war eines meiner Erstlingswerke, ohne try).

Werde nun, Eurem Rat folgend, mir TFilestream einmal genauer ansehen, wie dies gehen könnte. Oder kennt jemand einen Link auf ein Beispiel bei dem man spicken kann? Die Embarcadero-Hilfe zeigt zwar die Methoden, aber mir fehlen als Ungeübter die Beispiele.
Gruß hRb
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10146
Erhaltene Danke: 1235

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Fr 27.03.20 00:27 
Moin!

user profile iconhRb hat folgendes geschrieben Zum zitierten Posting springen:
Eigenartigerweise finde ich jedoch auch namensgleiche Dateien, die genau eine Stunde Differenzzeit aufweisen.
So eigenartig ist das gar nicht. ;) Das tritt auf oder kann auftreten, wenn man Sommerzeitunterschiede in zwei verschiedenen Dateisystemen (typisch: NTFS und FAT) hat. Die Differenz ist nur virtuell und auf die Art der Datumsspeicherung in den Dateisystemen zurückzuführen. :idea:

user profile iconhRb hat folgendes geschrieben Zum zitierten Posting springen:
Nun wollte ich mir ein eigenes Vergleichsprogramm schaffen.
Deinen Schaffensdrang in allen Ehren: wenn du einfach nur das Problem lösen willst (welches ausser dir noch ca. 3 Millionen Computernutzer weltweit sicher auch schon hatten :lol:), dann nimm doch einfach eines der bereits existierenden Tools, wie den FreeFileSync. :nixweiss: Das funktioniert bereits (und auch noch schnell), so dass du die Zeit in die Lösung des eigentlichen Problems investieren könntest. :angel:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4298
Erhaltene Danke: 925

Win10
C#, C++ (VS 2015/17)
BeitragVerfasst: Fr 27.03.20 07:46 
user profile iconhRb hat folgendes geschrieben Zum zitierten Posting springen:
Eigenartigerweise finde ich jedoch auch namensgleiche Dateien, die genau eine Stunde Differenzzeit aufweisen. Nun wollte ich mir ein eigenes Vergleichsprogramm schaffen.

Kennst du schon FreeFileSync (welches auch Zeitdifferenzen, welche meistens aufgrund von Sommer-/Winterzeit entstehen, beachtet)?

Edit: Ups, jetzt erst den letzten Beitrag von Narses gelesen ("2 Dumme, 1 Gedanke" - soll aber KEINE Beleidigung sein ;- ).
hRb Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 209
Erhaltene Danke: 12



BeitragVerfasst: Fr 03.04.20 22:30 
Hallo,
sorry, habe zu viel um die Ohren. So dauern Rückantworten bei mir immer etwas länger. Versuche auf die verschiedenen Fragen zu antworten.
1.
Zitat:
Kennst du schon FreeFileSync ...?
Nein, kannte ich bisher nicht. Habe es mal installiert. Sieht optisch gut ist und ist vermutlich auch ein sehr gutes leistungsfähiges Programm. Lande aber trotz Sprach-Einstellung "german" bei Hilfefragen immer im Internet auf einer englischen Hilfe-Seite.
2.
Zitat:
Deinen Schaffensdrang in allen Ehren: ... nimm doch einfach eines der bereits existierenden Tools.
Gedachtes Programm ist nicht für mich, sondern für meinen Bruder, der mit einem Rechner ganz bewusst keine Verbindung zum Internet herstellt / herstellen will. D.h. alle Programmme die zwangsweise (hier die Hilfe-Datei) aufs Internet zugreifen sind ungeeignet. Hilfe sollte zudem deutsch sein. Vielleicht weiß ja jemand ob und wo diese zu finden ist.

3. Habe Empfehlung aufgegriffen und meinen Quellcode mal von TMemoryStream auf TFileStream umgestellt und die Daten in einen Puffer eingelesen. Der Hinweis große Dateien scheibchenweise zu lesen ist ein überzeugendes Argument. Zur Hexa-Anzeige ist diese Methode auch ok. Allerdings: wenn ich eine Textdatei erkenne, mit welchem Aufruf lese ich dann die Zeilen ein?
Richedit1.Lines.LoadFromFile(Dateiname, vEncoding) ist halt eine bequeme Funktion und erledigt alles. Wenn man mir also die Verwendung von TFilestream empfiehlt, hat jemand ein fertiges Quellcodeschnippsel wie die Daten aus dem Puffer nach Richedit kommen? Möchte eigentlich nicht gerne Streams byteweise untersuchen und in Zeilen umwandeln. Da gibt es doch sicher etwas fertiges.
Danke wieder für Eure Geduld.
hRb

Moderiert von user profile iconTh69: Delphi-Tags hinzugefügt
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4298
Erhaltene Danke: 925

Win10
C#, C++ (VS 2015/17)
BeitragVerfasst: Sa 04.04.20 07:54 
Neben der LoadFromFile bietet die Klasse TStrings auch LoadFromStream - du solltest mehr Doku lesen. ;-)
hRb Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 209
Erhaltene Danke: 12



BeitragVerfasst: Di 14.04.20 21:12 
Hallo th69,
Zitat:
...du solltest mehr Doku lesen.
Hast im Grunde vollkommen recht. Lese allerdings in der Hilfe tatsächlich viel nach. Werde dort leider nicht immer fündig. Was den weniger Geübten häufig fehlt, sind Codeschnipsel (Beispiele). Die sind leider in diesem Forum nicht üppig.
Bin übrigens mit meinem Problem ein deutliches Stück weiter gekommen. Mal sehen, wann ich etwas "fertiges" vorstellen kann.
Habe leider an anderer Stelle neue Probleme. Danke zunächst für vorstehende Antworten.
hRb
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 18881
Erhaltene Danke: 1666

W10 x64 (Chrome, Edge)
Delphi 10.4 Ent, Oxygene, C# (VS 2019), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 15.04.20 06:43 
Für das Laden großer Dateien bieten sich MMFs an. Dafür habe ich damals einmal eine Unit vorgestellt:
entwickler-ecke.de/viewtopic.php?p=607865

Es gibt darauf basierend auch eine Stream-Klasse von Flamefire für den schnellen Zugriff:
entwickler-ecke.de/viewtopic.php?t=100088

Für den Dateivergleich würde es aber schon reichen jeweils eine MMF mit der Klasse im ersten Link aufzumachen und einfach nach und nach durchzugehen und die Teile zu vergleichen. Dafür sind MMFs sehr gut geeignet. Denn es wird jeweils ein Bereich der Datei in den Arbeitsspeicher gemappt, so dass nicht bei jedem Lesezugriff auf die Dateien zugegriffen werden muss. Ansonsten bremst das auf normalen Festplatten den Vergleich unnötig aus, da man zwei Dateien an verschiedenen Positionen abwechselnd lesen muss.
hRb Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 209
Erhaltene Danke: 12



BeitragVerfasst: Mi 15.04.20 21:15 
Hallo Jaenicke,
das ist nochmals ein super guter Hinweis. Habe zwar im Forum und im Internet gesucht, diesen Beitrag bisher jedoch nicht gefunden. Habe jetzt genug zum "Kauen".
PS: einige Links auf forum.delphi-treff... lassen sich leider nicht mehr öffnen, evtl verschoben. Scheint aber nur eine zweite weitere Zugriffsquelle zu sein
Vielen Dank hRb