| 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:
  				 | 									var   sl: 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 zusammengefasstIch 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.
 																	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;					 				 | 			 		 	  Moderiert von  Narses: Beiträge zusammengefasstNoch 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.  
 
 | 
 
 |  
 
 
 |