| 
| Autor | Beitrag |  
| gerd8888 
          Beiträge: 205
 Erhaltene Danke: 3
 
 Win7
 Delphi 10.1 Starter (kostenlos)  Lazarus
 
 | 
Verfasst: Sa 21.04.12 13:13 
 
Ich habe ein Filestream mit ansistring gefuellt. Ich habe unterschiedliche Laengen, die ich in einer Datei 1feld.dat abspeichere.
 In der Datei schreibe ich zunaechst rein:
 // In der Datei ifeld.dat befindet sich:
   // L
   // Lu
   // Luf
   // Luft
   // Luftb
   // Luftba
 Jetzt will ich in der zweiten Zeile das "LU" durch "Mond" ersetzen.
 Das klappt auch, nur eine winzige Kleinigkeit stoert mich:
 Es gibt eine Leerzeile dazwischen. Sieht dann so aus:
   //L
   //Mond
   //Luf
   //Luft
   //Luftb
   //Luftba
 Das kann nur daran liegen:
 		                       Delphi-Quelltext 
 									| 1:2:
 3:
 4:
 5:
 6:
 7:
 8:
 9:
 10:
 11:
 12:
 13:
 14:
 
 |   fs := TFileStream.Create (Filename, fmopenreadwrite);GetMem(Buf, BufSize);
 try
 Z := 0;
 Size := fs.Size;
 repeat
 if (Size-Z)-P < BufSize then N := (Size-Z)-P else N := BufSize;
 fs.Position := Size-Z-N;
 fs.Read(Buf^, N);
 fs.Position := Size-Z-N+Len;
 fs.Write(Buf^, N);
 Inc(Z, N);
 until (Size-Z) = P;
 |  												| 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:
 58:
 59:
 60:
 61:
 62:
 63:
 64:
 65:
 66:
 67:
 68:
 69:
 70:
 71:
 72:
 73:
 74:
 75:
 76:
 77:
 78:
 79:
 80:
 81:
 82:
 83:
 84:
 85:
 86:
 87:
 88:
 89:
 90:
 91:
 92:
 93:
 94:
 95:
 96:
 97:
 98:
 99:
 100:
 101:
 102:
 103:
 104:
 105:
 106:
 107:
 108:
 109:
 110:
 111:
 112:
 113:
 114:
 115:
 116:
 117:
 118:
 119:
 120:
 121:
 122:
 123:
 124:
 125:
 126:
 127:
 128:
 129:
 130:
 131:
 132:
 133:
 134:
 135:
 136:
 137:
 138:
 139:
 140:
 141:
 142:
 143:
 144:
 145:
 146:
 147:
 148:
 149:
 
 | unit Unit1;
 interface
 
 uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;
 
 
 
 type
 TForm1 = class(TForm)
 ListBox1: TListBox;
 Button7: TButton;
 procedure Button7Click(Sender: TObject);
 private
 
 public
 
 end;
 
 var
 Form1: TForm1;
 
 implementation
 
 {$R *.dfm}
 type Tdaten=ansistring;
 
 const st_laenge=8;
 linebr=2;
 
 procedure datei_leeren(Filename:string);
 var fs: TFileStream;
 begin
 fs := TFileStream.Create(Filename, fmOpenReadWrite or fmShareDenyWrite);
 try
 fs.Size := 0;
 finally
 fs.Free;
 end;
 end;
 
 
 procedure InsertData(Filename:string; const P, Len: Int64; insert: Tdaten);
 const
 BufSize = $00010000;
 var
 Buf: PChar;
 N: Integer;
 Size, Z: Int64;
 fs:Tstream;
 begin
 fs := TFileStream.Create (Filename, fmopenreadwrite);
 GetMem(Buf, BufSize);
 try
 Z := 0;
 Size := fs.Size;
 repeat
 if (Size-Z)-P < BufSize then N := (Size-Z)-P else N := BufSize;
 fs.Position := Size-Z-N;
 fs.Read(Buf^, N);
 fs.Position := Size-Z-N+Len;
 fs.Write(Buf^, N);
 Inc(Z, N);
 until (Size-Z) = P;
 
 fs.Position:=p;
 if insert <> '' then
 fs.Write (insert[1], len);
 fs.Write(sLineBreak, Length(sLineBreak));
 
 finally
 FreeMem(Buf, BufSize);
 end;
 fs.Free;
 end;
 
 
 
 procedure SaveStringToFile (st_laenge1:word; Filename:string; SaveString: tdaten; npos:integer);
 var
 fs: TFileStream;
 begin
 fs := TFileStream.Create (Filename, fmopenreadwrite);
 try
 fs.Position:=npos;
 if SaveString <> '' then
 fs.Write (SaveString[1], st_laenge1);
 fs.Write(sLineBreak, Length(sLineBreak));
 finally
 fs.Free;
 end;
 end;
 
 
 procedure TForm1.Button7Click(Sender: TObject);
 var str:string;
 i,id1,n:cardinal;
 data:tdaten;
 y:byte;
 breite:word;
 begin
 datei_leeren(ExtractFilePath(Application.ExeName) + '1feld.dat');
 
 str:='Luftballon';
 
 breite:=1; n:=0;
 savestringtofile(breite,ExtractFilePath(Application.ExeName) + '1feld.dat',str,n);
 breite:=2; n:=3;   savestringtofile(breite,ExtractFilePath(Application.ExeName) + '1feld.dat',str,n);
 breite:=3; n:=7;   savestringtofile(breite,ExtractFilePath(Application.ExeName) + '1feld.dat',str,n);
 breite:=4; n:=12;   savestringtofile(breite,ExtractFilePath(Application.ExeName) + '1feld.dat',str,n);
 breite:=5; n:=18;   savestringtofile(breite,ExtractFilePath(Application.ExeName) + '1feld.dat',str,n);
 breite:=6; n:=25;   savestringtofile(breite,ExtractFilePath(Application.ExeName) + '1feld.dat',str,n);
 
 
 
 
 insertdata(ExtractFilePath(Application.ExeName) + '1feld.dat',3,4,'Mond');
 
 
 
 
 end;
 
 end.
 |  |  |  |  
| Andreas L. 
          Beiträge: 1703
 Erhaltene Danke: 25
 
 Windows Vista / Windows 10
 Delphi 2009 Pro (JVCL, DragDrop, rmKlever, ICS, EmbeddedWB, DEC, Indy)
 
 | 
Verfasst: Sa 21.04.12 14:17 
 
Du kannst die Datenhaltung auch mit einer TStringList realisieren, das ersetzen geht dann mit StringReplace:
 		                       Delphi-Quelltext 
 									| 1:2:
 3:
 4:
 5:
 6:
 7:
 8:
 9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 
 | varsl: TStrings;
 begin
 sl := TStringList.Create;
 try
 sl.add('L');
 sl.Add('Lu');
 
 sl.Text := StringReplace(sl.Text, 'Lu', 'Mond', [rfReplaceAll]);
 
 sl.SaveToFile('C:\datei.txt');
 finally
 FreeAndNil(sl);
 end;
 end;
 |  |  |  |  
| gerd8888  
          Beiträge: 205
 Erhaltene Danke: 3
 
 Win7
 Delphi 10.1 Starter (kostenlos)  Lazarus
 
 | 
Verfasst: Sa 21.04.12 14:47 
 
Eine TStringlist wuerde fuer das Beispiel gut klappen und voellig ausreichen. 
Jedoch will ich mir ein eigenes Datenbanksystem aufbauen, dass die Daten gezielt ausliest.
 Bei einer TStringlist muss ich die ganzen Daten in den Arbeitsspeicher laden.
 Wenn man nichts groesseres vor hat, ist die TStringlist aber wirklich gut.
 |  |  |  
| Andreas L. 
          Beiträge: 1703
 Erhaltene Danke: 25
 
 Windows Vista / Windows 10
 Delphi 2009 Pro (JVCL, DragDrop, rmKlever, ICS, EmbeddedWB, DEC, Indy)
 
 | 
Verfasst: Sa 21.04.12 14:54 
 
	  |  gerd8888 hat folgendes geschrieben  : |  	  | Jedoch will ich mir ein eigenes Datenbanksystem aufbauen, dass die Daten gezielt ausliest.
 Bei einer TStringlist muss ich die ganzen Daten in den Arbeitsspeicher laden.
 
 | 
 Vielleicht wäre dann eine Dateibasierte Datenbank wie SQLite etwas für dich?
 Ich verwende dazu diese Klassen: www.delphipraxis.net...atabase-wrapper.html Ist echt super    |  |  |  
| gerd8888  
          Beiträge: 205
 Erhaltene Danke: 3
 
 Win7
 Delphi 10.1 Starter (kostenlos)  Lazarus
 
 | 
Verfasst: Sa 21.04.12 15:07 
 
Mal sehen, wenn das mit meiner Datenbank nicht klappt, probiere ich das mal aus.Moderiert von  Narses: Beiträge zusammengefasst Ich habe es jetzt selbst herausgefunden.
 Ich verschiebe das ganze einfach um (die neue Breite-urspruengliche Breite) 6-4=2 (die Positionen 7 und 3 habe ich in einer Datei abgespeichert, 
 also 7-3=4) also 6-4 nach rechts, dann ist die richtige Luecke (4 + linebr) entstanden,
 da schreibe ich dann den gewünschten Inhalt. Schaut jetzt etwas kaotisch aus, aber so geht es.
 			Moderiert von									| 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 InsertData(Filename:string; const P, Len: Int64; insert: Tdaten);
 var
 loadstring, savestring:tdaten;
 
 fs:TFilestream;
 st_laenge:word;
 verschieben:integer;
 begin
 fs := TFileStream.Create (Filename, fmopenreadwrite);
 
 fs.Position:=7;
 st_laenge:=24;   SetLength (LoadString, st_laenge);
 fs.Read(loadstring[1],st_laenge);
 verschieben:=2;   fs.Size:=fs.Size+verschieben;
 form1.listbox1.Items.Add('->'+loadstring);
 
 fs.Position:=7+verschieben;
 fs.Write(loadstring[1], st_laenge);
 
 fs.Position:=3;
 fs.Write (insert[1], 4);
 fs.Write(sLineBreak, Length(sLineBreak));
 
 fs.Free;
 end;
 |   Narses: Beiträge zusammengefasst Noch kurz:
 1. 
 str:='Luftballon'; str:tdaten (ansistring und nicht string)
 und st_laenge:=26 und nicht 24, da filesize=33 (und nicht 31) da ganz hinten noch ein linebr.
 2.
 es funktioniert auch mit Verkuerzung so, indem man bei verschieben:=-1 (deshalb integer) und eben nur einen Buchstaben -B- 
  fs.Position:=3;
  //   if insert <> '' then
       fs.Write (insert[1]{Pointer(savestring)^}, 1{Length (insert)});
       fs.Write(sLineBreak, Length(sLineBreak));
 L
 B
 LUF
 LUFT
 usw.
 3. Ich glaube, dass diese Methode sehr schnell ist, da er nicht einzeln Buchstabe fuer Buchstabe, sondern die ganze Stringkette nach 
 rechts schiebt. Jetzt weiss ich bloss nicht, wieviel st_laenge das maximum ist. Dann muesste man es lediglich auf das max. hin verkleinern
 und in mehreren Teilschritten ausführen. Sollte aber auch kein so grosses Problem sein. |  |  |  |