TFileStream - Speichern und Lesen

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
RuhrPotto
Beiträge: 39
Registriert: Mi 6. Mai 2015, 12:52

TFileStream - Speichern und Lesen

Beitrag von RuhrPotto »

Hai!
Hab wohl wieder den Tag mit Brett.
Ein gleichlauten Eintrag hab ich im Forum gefunden - aber ich komm nicht weiter.

Folgende CodeStrecke funzt

Code: Alles auswählen

 
size, len : longint;
 
**** SPEICHERN ***
 
for i := 0 to Length(Daten) - 1 do begin
      Stream.Write(Daten[i].ID, SizeOf(Daten[i].ID));   // ID Speichern als Integer
      Len := Length(Daten[i].Name);
      Stream.Write(Len, SizeOf(Len));                   // Länge des Stringes speichern
      Stream.Write(Pointer(Daten[i].Name)^, Len);       // Den String selbst speichern
    end;
 
**** LADEN ****
...
for i := 0 to Len - 1 do begin
      Stream.Read(Daten[i].ID, SizeOf(Daten[i].ID));    //-- brauch ich nicht
      Stream.Read(size, SizeOf(size));
      SetLength(Daten[i].Name, size)//Teil eines Records - Ansistring
      Stream.Read(Pointer(Daten[i].Name)^, size);
end;
 
//Anmerkung size=4Byte= x'80000000'
 


Ich muß im Programm nur große Strings random lesen und verarbeiten. Daher hab ich

Code: Alles auswählen

 
 
AString : AnsiString;
size, len : longint;
 
****SPEICHERN ****
    Len := Length(AString);
    Stream.Write(Len, SizeOf(Len));                   // Länge des Stringes speichern
    Stream.Write(Pointer(AString)^, Len);             // Den String selbst speichern
 
****LADEN ****
...
   //pos := 0;
   //Stream.Seek(pos,soBeginning);  --für später
...
    Stream.Read(size, SizeOf(size));
    SetLength(AString, size);
    Stream.Read(Pointer(AString)^, size);
 
//Anmerkung auch hier size=4Byte= x'80000000'
 

nur den Stringteil verwendet.
Erstere Lösung geht, zweite nicht.

Als size lese ich immer den Wert 4 (bei der der ersten Variante 128 was mommentan OK wäre)

Jemand eine Idee?
Danke
Jeder macht Fehler - viele Fehler brauchen EDV!

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: TFileStream - Speichern und Lesen

Beitrag von theo »

Nimm Stream.WriteAnsiString();

RuhrPotto
Beiträge: 39
Registriert: Mi 6. Mai 2015, 12:52

Re: TFileStream - Speichern und Lesen

Beitrag von RuhrPotto »

Stream kennt kein WriteAnsiString
Jeder macht Fehler - viele Fehler brauchen EDV!

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: TFileStream - Speichern und Lesen

Beitrag von wp_xyz »

RuhrPotto hat geschrieben:random lesen und verarbeiten

Wenn du mit "random lesen" meinst, dass du die Strings in beliebiger Reihenfolge haben willst, musst du wissen, bei welcher Stream-Position die Strings jeweils beginnen. Das heißt, du musst einmal den Stream von vorne bis hinten durchlaufen und dabei diese Tabelle aufbauen. Dazu reicht ein Array von Integern (oder Int64), in dem du die jeweiligen Stream-Positionen speicherst. Später, wenn du den String mit Index I lesen willst, schaust du in der Tabelle nach, an welcher Stream-Position sich der String befindet, springst an diese Position und liest den String ein so wie in deinem Code ausgeführt.

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: TFileStream - Speichern und Lesen

Beitrag von theo »

RuhrPotto hat geschrieben:Stream kennt kein WriteAnsiString

Aber TFileStream. Steht so in deiner Überschrift.

Mathias
Beiträge: 6163
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: TFileStream - Speichern und Lesen

Beitrag von Mathias »

theo hat geschrieben:
RuhrPotto hat geschrieben:Stream kennt kein WriteAnsiString

Aber TFileStream. Steht so in deiner Überschrift.

Bei mir kennt er es auch bei TStream.

Folgendes wird bei mir anstandslos kompiliert.

Code: Alles auswählen

var
  st: TStream;
begin
.... // Create, etc.
  st.WriteAnsiString('abc');
end;
 
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

RuhrPotto
Beiträge: 39
Registriert: Mi 6. Mai 2015, 12:52

Re: TFileStream - Speichern und Lesen

Beitrag von RuhrPotto »

Also erstmal Danke für die Antworten!

Und Upps - muss diesmal "fremdgehen" und das ganze mal wieder mit Delphi (auch noch ne aktuelle Starter) machen :(

Ich arbeite auf mehreren HOST-Entladebeständen mit fester Satzgröße (String 512 - 4096 Bytes).
Den/die Indexe muss ich selber erstellen. Ist auch kein Problem.

Ich bekomme die Daten halt nicht in einen Stream mit Random-Zugriff; selbst wenn ich den Index im Speicher habe.
Und ich hab das "Brett", warum es beim Speichern mit einem Array of Record (Beispiel: Integer- und AnsiString-Feld) klappt und bei reinen Strings nicht!?!

Das definierte Vorgehen wäre doch
- Ermitteln Stringlänge
- Speichern Stringlänge
- Speichern String (Pointer, PChar oder string[1])

Etwas anderes macht WriteAnsiString doch auch nicht:
"WriteAnsiString writes the AnsiString S (i.e. 4 bytes) to the stream. This is a utility function which simply calls the Write function. The ansistring is written as a 4 byte length specifier, followed by the ansistring's content."!
Jeder macht Fehler - viele Fehler brauchen EDV!

Mathias
Beiträge: 6163
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: TFileStream - Speichern und Lesen

Beitrag von Mathias »

Code: Alles auswählen

   Stream.Write(Pointer(AString)^, Len);    

Müsste dies nicht

Code: Alles auswählen

if Len > 0 then Stream.Write(AString[1], Len);    

heisen ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: TFileStream - Speichern und Lesen

Beitrag von wp_xyz »

Ich bin 100% sicher, dass dein Problem mit den Lese/Schreibe-Routinen nichts zu tun hat, sondern mit der Erstellung des Index.

In der beigefügten Demo werden mit dem Button "Stream erzeugen" zufällige Strings erzeugt, die aber zur besseren Unterscheidung immer dieselbe Ziffer enthalten. Die Strings werden in der Listbox darunter angezeigt, wobei der Stream-Offset, bei dem jeder String beginnt, vorangestellt ist.

Mit dem Button "Index erzeugen" wird der Stream schnell eingelesen und der Index erzeugt, also die Positionen wiederum, wo ein String beginnt. Diese werden in der Listbox darunter angezeigt. Die Index-Werte stimmen exakt mit den Offsets in der linken Liste überein.

Mit dem Button "Auslesen" wird im Index der Eintrag mit dem im SpinEdit angegebenen Index ausgewählt, der Stream springt an die entsprechende Position, der String wird eingelesen und in die Listbox darunter eingetragen. Jeder angezeigte String enthält wie erwartet immer dieselben Zeichen, und die Länge stimmt auch.
Dateianhänge
stream_rnd_access.zip
(2.43 KiB) 78-mal heruntergeladen

RuhrPotto
Beiträge: 39
Registriert: Mi 6. Mai 2015, 12:52

Re: TFileStream - Speichern und Lesen

Beitrag von RuhrPotto »

Hi
und Danke @ wp_xyz für die viele Arbeit!!
Bin jetzt ausgebrannt nach 12 Stunden ... und schau es mir morgen genauer an

Ich hab noch keinen Index sondern will die Strings nur einlesen und dann im FileStream speichern.
Anschließend sequentiell lesen und Indexe erstellen.

Einlesen und anzeigen (Memo) klappt - nur speichern nicht.

Mit Testdaten sehen die Dateien aus wie im Anhang - eigentlich Ok..
.
nur String Daten
nur String Daten
Array of Record Daten
Array of Record Daten
Jeder macht Fehler - viele Fehler brauchen EDV!

Antworten