Autor Beitrag
gerd8888
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 205
Erhaltene Danke: 3

Win7
Delphi 10.1 Starter (kostenlos) Lazarus
BeitragVerfasst: Sa 21.04.12 14: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:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
// nach rechts verschieben
  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;





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:
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
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  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:stringconst P, Len: Int64; insert: Tdaten);
const
  BufSize = $00010000;
var
  Buf: PChar;
  N: Integer;
  Size, Z: Int64;
  fs:Tstream;
begin
  // nach rechts verschieben
  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;

    //einfügen
    fs.Position:=p;
    if insert <> '' then
      fs.Write (insert[1]{Pointer(savestring)^}, len{Length (SaveString)});
      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]{Pointer(savestring)^}, st_laenge1{Length (SaveString)});
      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//1+(linebr=2)+0 =3
  savestringtofile(breite,ExtractFilePath(Application.ExeName) + '1feld.dat',str,n);
  breite:=3; n:=7//3+(linebr=2)+2 =7
  savestringtofile(breite,ExtractFilePath(Application.ExeName) + '1feld.dat',str,n);
  breite:=4; n:=12//7+(linebr=2)+3=12
  savestringtofile(breite,ExtractFilePath(Application.ExeName) + '1feld.dat',str,n);
  breite:=5; n:=18//12+(linebr=2)+4=18
  savestringtofile(breite,ExtractFilePath(Application.ExeName) + '1feld.dat',str,n);
  breite:=6; n:=25//18+(linebr=2)+5=23
  savestringtofile(breite,ExtractFilePath(Application.ExeName) + '1feld.dat',str,n);

  // In der Datei ifeld.dat befindet sich:

  // L
  // Lu
  // Luf
  // Luft
  // Luftb
  // Luftba


  // jetzt will ich in der zweiten Zeile das "LU" entfernen und "Mond" hineinschreiben
  insertdata(ExtractFilePath(Application.ExeName) + '1feld.dat',3,4,'Mond');
  // Fast waere es gegangen aber eine störende Leerzeile:

  //L
  //Mon

  //Luf
  //Luft
  //Luftb
  //Luftba

  //Wie verhindere ich die Leerzeile, die stoert mich

end;

end.
Andreas L.
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1703
Erhaltene Danke: 25

Windows Vista / Windows 10
Delphi 2009 Pro (JVCL, DragDrop, rmKlever, ICS, EmbeddedWB, DEC, Indy)
BeitragVerfasst: Sa 21.04.12 15:17 
Du kannst die Datenhaltung auch mit einer TStringList realisieren, das ersetzen geht dann mit StringReplace:

ausblenden 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
    // Zeilen hinzufügen
    sl.add('L');
    sl.Add('Lu');
    // etc.
    
    // Ersetzen
    sl.Text := StringReplace(sl.Text, 'Lu''Mond', [rfReplaceAll]);

    // Liste speichern
    sl.SaveToFile('C:\datei.txt');
  finally
    FreeAndNil(sl);
  end;
end;
gerd8888 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 205
Erhaltene Danke: 3

Win7
Delphi 10.1 Starter (kostenlos) Lazarus
BeitragVerfasst: Sa 21.04.12 15: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.
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1703
Erhaltene Danke: 25

Windows Vista / Windows 10
Delphi 2009 Pro (JVCL, DragDrop, rmKlever, ICS, EmbeddedWB, DEC, Indy)
BeitragVerfasst: Sa 21.04.12 15:54 
user profile icongerd8888 hat folgendes geschrieben Zum zitierten Posting springen:

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 :zustimm:
gerd8888 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 205
Erhaltene Danke: 3

Win7
Delphi 10.1 Starter (kostenlos) Lazarus
BeitragVerfasst: Sa 21.04.12 16:07 
Mal sehen, wenn das mit meiner Datenbank nicht klappt, probiere ich das mal aus.

Moderiert von user profile iconNarses: 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.


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:
32:
33:
34:
35:
procedure InsertData(Filename:stringconst P, Len: Int64; insert: Tdaten);

var
  loadstring, savestring:tdaten;

  fs:TFilestream;
  st_laenge:word;
  verschieben:integer;
begin
  // nach rechts verschieben
  fs := TFileStream.Create (Filename, fmopenreadwrite);

  fs.Position:=7;
  st_laenge:=24//31-7
  SetLength (LoadString, st_laenge);
  fs.Read(loadstring[1],st_laenge);
  verschieben:=2//Len-  (0,3,7,12,18...) da 7-3=4 also Len=6 - 4
  fs.Size:=fs.Size+verschieben;
  form1.listbox1.Items.Add('->'+loadstring);

  fs.Position:=7+verschieben;
  fs.Write(loadstring[1]{Pointer(savestring)^}, st_laenge{Length (SaveString)});
  //fs.Write(sLineBreak, Length(sLineBreak));

    //einfügen
    fs.Position:=3;
 //   if insert <> '' then
      fs.Write (insert[1]{Pointer(savestring)^}4{Length (insert)});
      fs.Write(sLineBreak, Length(sLineBreak));

  //finally
    //FreeMem(Buf, BufSize);
  //end;
  fs.Free;
end;


Moderiert von user profile iconNarses: 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.