![]() |
Array als Datei speichern
Hallo.
Ich möchte mit einem Programm ein Array als Datei abspeichern und auch wieder öffnen und auslesen. Wie kann ich das realisieren? |
Re: Array als Datei speichern
Hi.
Das kommt auf das array an. Statisches oder dynamisches / ein oder mehrdimensional? Ich würde auf jeden fall streams verwenden. Wenn dann noch statisch ist, dann kannste es in einem rutsch in die datei streamen: zb.
Delphi-Quellcode:
cu
var fs:TFileStream;
arr:array[0..99] od integer; ... fs:=TFileStream.create('c:\array.dat',fmCreate); try fs.write(arr,sizeOf(arr)); finally fs.free; end; |
Re: Array als Datei speichern
Danke schonmal.
Das Array ist eindimensional und statisch. Und wie lese ich das Array jetzt wieder aus? |
Re: Array als Datei speichern
Das geht relativ einfach über eine TStringList und FOR-Schleifen:
Delphi-Quellcode:
Sollte auch einfach auf andere Typen anwendbar sein.
var map: array [1..256] of byte;
... procedure Thaupt.Save(Sender: TObject); var StrList: TStrings; i: integer; begin if SaveDialog1.Execute then begin StrList := NIL; try StrList := TStringList.Create; for i:=1 to 256 do begin StrList.Add(IntToStr(map[i])); end; StrList.SaveToFile(SaveDialog1.FileName); finally StrList.Free; end; end; end; procedure Thaupt.Open(Sender: TObject); var StrList: TStrings; i: integer; begin if OpenDialog1.Execute then begin StrList := NIL; try StrList := TStringList.Create; StrList.LoadFromFile(OpenDialog1.FileName); for i:=1 to 256 do begin map[i] := StrToInt(StrList[i]); end; finally StrList.Free; end; end; |
Re: Array als Datei speichern
@H4ndy: Wers möglichst dirty und nicht binär haben will, der soll es so machen, wie du vorschlägst :mrgreen:
Zitat:
Delphi-Quellcode:
cu.
var fs:TFileStream;
arr:array[0..99] od integer; ... if fileExists('c:\array.dat') then begin fs:=TFileStream.create('c:\array.dat',fmOpenRead); try if fs.size >= sizeOf(arr) then fs.read(arr,sizeOf(arr)); finally fs.free; end; end else showMessage('foobar not da'); |
Re: Array als Datei speichern
Zitat:
Quick'n'Dirty ist mein zweiter Vorname :zwinker: @maximov: Klappt das mit dem FileStream auch für 2-dimensionale Arrays? |
Re: Array als Datei speichern
Zitat:
cu. |
Re: Array als Datei speichern
Kann ich denn auch dynamische Array mit FileStream abspeichern?
|
Re: Array als Datei speichern
Zitat:
|
Re: Array als Datei speichern
Da hast du natürlich recht :cyclops:
Ich fake gern dynamische arrays mit statischer deklaration als pointer und um die reservierung kümmere ich mich dann selbst (zb. für DirectX programmierung sehr praktisch)...man muss sich nur die länge der gültigen daten merken. @Hummer: sollte auch kein prob sein. evtl. musst du einfach auf das erste element referenzieren und dann length()-bytes lesen:
Delphi-Quellcode:
oder so.
if length(arr)>0 then fs.write(@arr[0]^,length(arr)*sizeOf(Element));
|
Re: Array als Datei speichern
ich habe ein ähnliches Problem. Bei mir ist der Array mit dem Typ Record verknüpft:
Delphi-Quellcode:
im Privat Bereich :
type
zeiten= record name: string; bzeit: string; versuch: integer; end;
Delphi-Quellcode:
Danach werden die Werte jeweils durch die Aktionen des Users gesetzt. Danach möchte ich, dass er es speichern und auch wieder laden kann, jedoch funktioniert das nicht mit den oben aufgeführten Möglichkeiten.
testr : array[1..20] of zeiten;
Ich habe auch schon Tutorials wie ![]() Ich hoffe ihr könnt mich einen kleinen Tipp geben. MfG |
Re: Array als Datei speichern
|
Re: Array als Datei speichern
Nimm mal ShortStrings in deinem Record.
|
Re: Array als Datei speichern
Zitat:
Delphi-Quellcode:
Jedoch speichert dieser code nur 'normale' record und keinen, der mit einem Array in verbindung steht. Außerdem wird hier auch kein TWriter oder TReader benutzt, was ich ja gerade benutzten sollte, wegen der Strukturen. Auch die Delphi Hilfe schweigt bei der eingabe von TWriter....
procedure WriteStringToStream(stream: TFileStream; str: string);
var len: integer; begin len := length(str); // Länge des strings ermitteln stream.write(len, SizeOf(len)); // Länge des Strings speichern stream.write(PChar(str)^, len); // String mittels PChar speichern end; procedure ReadStringFromStream(stream: TFileStream; var str: string); var len: integer; begin stream.read(len, SizeOf(len)); // Länge des Strings auslesen SetLength(str, len); // Länge des Srings setzen stream.read(PChar(str)^, len); // Strings mittels PChar auslesen end; --> nur unter der Wortsuche fand ich einen kleinen Artikel der jediglich die eigenschaften beschrieb, jedoch nicht auf die Syntaxs einging. MfG |
Re: Array als Datei speichern
So geht es:
Delphi-Quellcode:
// unser Record
type TScoreRecord = packed record Player: string[25]; Score: Cardinal; end; // unser Array vom Typ unseres Records var ScoreRecord: array[0..2] of TScoreRecord; procedure TForm1.Button1Click(Sender: TObject); var fs: TFileStream; begin // Array fülllen ScoreRecord[0].Player := 'Hans'; ScoreRecord[0].Score := 5; ScoreRecord[1].Player := 'Fritz'; ScoreRecord[1].Score := 6; ScoreRecord[2].Player := 'Lieschen'; ScoreRecord[2].Score := 4; // abspeichern fs := TFileStream.Create('d:\HighScore.hs', fmCreate); try try // Array in Datei schreiben fs.WriteBuffer(ScoreRecord, sizeof(ScoreRecord)); except // Schreibfehler aufgetreten on E: EWriteError do ShowMessage(E.Message); end; finally // fs wieder freigeben FreeAndNil(fs); end; end; procedure TForm1.Button2Click(Sender: TObject); var fs: TFileStream; i: Integer; begin fs := TFileStream.Create('d:\HighScore.hs', fmOpenRead); try try // erstmal wieder leeren for i := 0 to length(ScoreRecord) - 1 do begin ScoreRecord[i].Player := ''; ScoreRecord[i].Score := 0; end; // aus Datei einlesen fs.ReadBuffer(ScoreRecord, sizeof(ScoreRecord)); // und kucken was drinne steht for i := 0 to length(ScoreRecord) - 1 do begin ShowMessage(ScoreRecord[i].Player+#13#10+IntToStr(ScoreRecord[i].Score)); end; except // Lesefehler aufgetreten on E: EReadError do ShowMessage(E.Message); end; finally // fs wieder freigeben FreeAndNil(fs); end; end; |
Re: Array als Datei speichern
Zitat:
Tu dir selbst einen gefallen und fang garnicht erst an, records direkt binär zu speichern, erst recht nicht wenn da shortStrings drinn sind (platzverschwendung). Wenn du zB. die lange des strings, oder daten hinzufügen willst, dann ist das format deiner alten daten inkompatibel. Ich mach es oft so, das ich erst eine signatur, versions-nummer und ein schema speichere, das besagt welche daten geschrieben werden. Beim auslesen weiss man dann genau, was man wohin laden muss. |
Re: Array als Datei speichern
Zitat:
habt ihr vieleicht einen Konkreten link etc... MfG @Luckie thx, werde ich sofort mal testen |
Re: Array als Datei speichern
Zitat:
|
Re: Array als Datei speichern
nunja funktionieren stelle ich mir anders vor :P
Also es funktioniert nur einmal. Bei einem erneuten ausführen der laden funktion stüzt delphi komplett ab :D, wegen einer "Zugriffsverletzung". Außerdem zeigt er mir nicht die Werte an, er zeigt nichts an im "showmessage": Code sieht so aus:
Delphi-Quellcode:
type
zeiten= packed record name: string; bzeit: string; versuch: integer; end; var testr : array[1..20] of zeiten; procedure TForm1.SpeedButton3Click(Sender: TObject); var fs: TFileStream; i: Integer; begin fs := TFileStream.Create('d:\HighScore.hs', fmOpenRead); try try // erstmal wieder leeren for i := 0 to length(testr) - 1 do begin testr[i].bzeit := ''; testr[i].name := ''; testr[i].versuch := 0; end; // aus Datei einlesen fs.ReadBuffer(testr, sizeof(testr)); // und kucken was drinne steht for i := 0 to length(testr) - 1 do begin ShowMessage('Bzeit:'+testr[i].bzeit+#13#10+'Verusch:'+IntToStr(testr[i].versuch)+#13#10+'name'+testr[i].name); end; except // Lesefehler aufgetreten on E: EReadError do ShowMessage(E.Message); end; finally // fs wieder freigeben FreeAndNil(fs); end; end; procedure TForm1.SpeedButton2Click(Sender: TObject); var outputfile : textfile; i : word; StrList: TStrings; y: integer; fs: TFileStream; begin testr[1].name := 'muh'; testr[2].name := 'jta'; fs := TFileStream.Create('d:\HighScore.hs', fmCreate); try try // Array in Datei schreiben fs.WriteBuffer(testr, sizeof(testr)); except // Schreibfehler aufgetreten on E: EWriteError do ShowMessage(E.Message); end; finally // fs wieder freigeben FreeAndNil(fs); end; end; |
Re: Array als Datei speichern
Liste der Anhänge anzeigen (Anzahl: 1)
Bei mir definitiv nicht, sonst hätte ich das hier nicht gepostet.
Demo im Anhang. |
Re: Array als Datei speichern
Ich frage mich, warum er bei dir nicht abstürzt und bei mir schon :/ grml. Ich hbae den code nur angepasst, nicht mehr.
code : siehe editieren Beitrag MfG //edit: wenn ich bei mir erst "lesen" lasse und dann auf speichern klicke stürzt das Programm ebenfalls mit einer Zugriffsverletzung ab. |
Re: Array als Datei speichern
Du benutzt nach wie vor normale strings in deinem record, und nicht string[?].
Zu TReader und TWriter (Filer) hab ich hier mal was geschrieben: ![]() |
Re: Array als Datei speichern
Zitat:
Vielleicht ist es für dich trivial, jedoch vermag ich es nicht zu verstehen. MfG |
Re: Array als Datei speichern
Du musst ShortStrings benutzen, also entwerde
Delphi-Quellcode:
oder mit direkter Längenangabe:
s: ShortString;
Delphi-Quellcode:
s: String[55];
|
Re: Array als Datei speichern
@maximov
Hattest du nicht zusammen mit Jens einen TCollection descendant gebastelt? Ich hatte ihn nie ausprobiert, aber mit Interesse euren Fortschritt verfolgt. Ich persönlich ziehe Objekte dem Hantieren mit primitiven Typen vor, mit dem TCollection-Abkömmling bekommt man anscheinend eine hübsche Möglichkeit zur Objektpersistenz. ;) Nachtrag: Hab's gefunden... ![]() |
Re: Array als Datei speichern
Delphi-Quellcode:
Beim zweiten Mal stürzt das Programm ebenfalls ab. Angeblich wieder wegen einer Zugriffsverletzung ( Habe strings auf 10 Zeichen begrenzt!)
procedure TForm1.SpeedButton3Click(Sender: TObject);
var fs: TFileStream; m: Integer; begin if opendialog1.execute then begin fs := TFileStream.Create(OpenDialog1.FileName, fmOpenRead);{ExtractFilePath(ParamStr(0))+'HighScore.hs'} try try // erstmal wieder leeren for m := 0 to length(testr) - 1 do begin testr[m].bzeit := ''; testr[m].name := ''; testr[m].versuch := 0; end; // aus Datei einlesen fs.ReadBuffer(testr, sizeof(testr)); except // Lesefehler aufgetreten on E: EReadError do ShowMessage(E.Message); end; finally // fs wieder freigeben FreeAndNil(fs); end; end; end; Wenn ich es ohne OpenDialog mache klappt es wunderbar. Dafür schon mal ein großes Dankeschön :) MfG |
Re: Array als Datei speichern
Dann geh mal mit F7 durch den Quellcode durch.
|
Re: Array als Datei speichern
Mit TReader und TWriter habe ich nur schlechte Erfahrungen gemacht, z.B. war die Größe des Filestreams nach den ersten Aufruf von ReadString() plötzlich Null. Für einfache Datentypen wie Integer, String und Double hab ich mir deshalb einfache, eigene TFiler-Klassen zusammengeschustert... die sind aber so billig, dass ich mich nicht traue, die jetzt auch noch hier reinzuposten *g*
PS: Es ist zwar Geschmackssache, aber anstelle eines Arrays würde ich eher zu TList und anstelle von Records eher zu class(TObject) tendieren |
Re: Array als Datei speichern
@Mr_Anderson
Delphi-Quellcode:
var testr : array[[color=red]1[/color]..20] of zeiten;
Delphi-Quellcode:
du definierst dein array von 1.. und greifst aber auf 0. Element zu. über eine Zugriffsverletzung brauchst du dich dann nicht zu wundern ;)
// erstmal wieder leeren
for m := [color=red]0[/color] to length(testr) - 1 do begin testr[m].bzeit := ''; testr[m].name := ''; testr[m].versuch := 0; end; Zitat:
Mfg Frank |
Re: Array als Datei speichern
Hi
Warum eigentlich immer so ganz kleine Fehler mir passieren :) :wall: :wall: Herzlichen Dank an Keldorn. Jetzt funktioniert es. Was mich jetzt dennoch interessiert, was du damit genau meinst Zitat:
MfG |
Re: Array als Datei speichern
wenn du daten aus einem stream lädst, mußt du sie genausso einlesen, wie du sie reingeschrieben hast. Wenn sich dein Record mal erweitert, weil du der Meiniung bist, das du noch ein weiteres Feld benötigst, dann hast du ein Problem. Deine vorher gespeicherten Daten passen nun nicht mehr und du müßtest dir ein konvertierungsprogramm schreiben, das dir die alten Daten auf das neue format "anpaßt", gerade wenn du in der Entwicklung bist und du noch nicht richtig weißt, wie dein Record/Object aufgebaut ist, kostet dich das unnötig viel Zeit und kann schnell Fehler verursachen.
Es gibt da sicher noch andere Lösungsmöglichkeiten, ich hab mich dafür entschieden und bin recht glücklich damit. die "falschen" Einrückungen sind Absicht:
Delphi-Quellcode:
//Versionskonstanten fürs Speichern/Laden der Daten
const Version1 = 1; Version2 = 2; Version3 = 3; Version4 = 4; Version_neu = 4; … procedure TSendung.LoadFromStream(stream: TStream); var Version:integer; begin with TReader.create(Stream,1024) do try begin //Version auslesen Version:=ReadInteger; Auftrag := readstring; Kunde := readstring; Kundennummer := readstring; PLZ := readstring; Ort := readstring; Land := readstring; VA_Typ := ReadInteger; if version>=Version2 then begin Bestelldaten := readstring; AuftragsArt := readstring; Baunummer := readstring; end; if version>=Version3 then begin KdNrVertretung := readstring; end; //hier hinzufügen end; finally free; end; end; procedure TSendung.SaveToStream(stream: TStream); //Daten in Stream Speichern begin with Twriter.create(Stream,1024) do try begin //version schreiben writeinteger(Version_neu); //Daten schreiben writestring(Auftrag); writestring(Kunde); writestring(Kundennummer); writestring(PLZ); writestring(Ort); writestring(Land); writeinteger(VA_Typ); WriteString(Bestelldaten); writestring(AuftragsArt); writestring(Baunummer); writestring(KdNrVertretung); //hier hinzufügen end; finally free; end; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:20 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz