Autor |
Beitrag |
gerd8888
Beiträge: 205
Erhaltene Danke: 3
Win7
Delphi 10.1 Starter (kostenlos) Lazarus
|
Verfasst: 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:
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 15: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 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.
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 15: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 16: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.
|
|
|