Jeg ville (som sædvanligt) gå til min favoritløsning: En TObjectList der indeholder objekter der kan have en liste af 12 1 1'ere. Det vil tage mig en middagspause at strikke en kørbar løsning sammen om du er interesseret - med kobling til TTreeView (selvom dette er ret langsomt om man har mange TTreeNodes).
Er
100000, 20000 { 12 1 1 13 1 1 }
en dataenhed eller står 100000 alene? Med andre ord: Hvordan er strukturen? Skal data kunne skrives anden enhed?
jeg har lavet en mindre fejl, data står som følgende:
"100000" 20000 { 12 1 1 13 1 1 } jeg skal bruge data til videre forarbejdelse, bla smide i en database. men det ville være rart med en lille løsning, du kan dog bare pege mig i rette vej hvis det er for omstændigt at lave et komplet eksempel
TSegmentSubData = class private fSubData : TStringList; function GetString(const aIndex: integer): string; public constructor Create(const aString : string); destructor Destroy; override; property Items[const aIndex : integer] : string read GetString; default; function Count : integer; end;
implementation
{ TDataList }
type TStringStates = (ssHeader, ssSegment);
constructor TDataList.Create(const aFileName: string); var fp : TextFile; st : string; StringState : TStringStates; SegmentData : TSegmentData; // SegmentSubData : TSegmentSubData; begin inherited Create(true); fFileName := aFileName; SegmentData := nil;
assignfile(fp,fFileName); reset(fp); try StringState := ssHeader; while not eof(fp) do begin readln(fp,st); st := trim(st); if st <> '' then case StringState of ssHeader : begin SegmentData := TSegmentData.Create(st); if pos('{',st) > 0 then StringState := ssSegment; end; ssSegment : if st = '}' then begin if not assigned(SegmentData) then raise Exception.Create('Error in file structure'); Add(SegmentData); // Add finished record object to list StringState := ssHeader; end else SegmentData.Add(TSegmentSubData.Create(st)); end; // case end; finally closefile(fp); end; end;
function TDataList.GetSegmentData(const aIndex: integer): TSegmentData; begin result := TSegmentData(inherited Items[aIndex]); end;
{ TSegmentData }
constructor TSegmentData.Create(const aString: string); var p1,p2 : integer; begin inherited Create(true); p1 := pos(',',aString); if p1 > 0 then begin fField1 := copy(aString,2,p1-3); p2 := pos('{',aString); if p2 = 0 then fField2 := StrToInt(trim(copy(aString,p1+1,MaxInt))) else fField2 := StrToInt(trim(copy(aString,p1+1,p2-p1-1))); end; end;
function TSegmentData.GetSegmentSubData(const aIndex: integer): TSegmentSubData; begin result := TSegmentSubData(inherited Items[aIndex]); end;
{ TSegmentSubData }
function TSegmentSubData.Count: integer; begin result := fSubData.Count; end;
destructor TSegmentSubData.Destroy; begin try fSubData.Free; finally inherited; end; end;
function TSegmentSubData.GetString(const aIndex: integer): string; begin result := fSubData[aIndex]; end;
end.
og her er rutinen der gennemløber strukturen:
procedure TfrmMain.Button1Click(Sender: TObject); var Data : TDataList; i,j,k : integer; begin Data := TDataList.Create('test.txt'); try for i := 0 to Data.Count - 1 do begin mLog.Lines.Add(format('%s %d',[Data[i].Field1,Data[i].Field2])); for j := 0 to Data[i].Count - 1 do for k := 0 to Data[i][j].Count - 1 do mLog.Lines.Add(Data[i][j][k]); end; finally Data.Free; end; end;
Jeg har forudsat at filen findes (i constructoren) og at sub-data afslutteren } altid står alene på linien - så har jeg sikkert forudsat en del mere, men det kan jeg ikke huske - er sulten og vil ned og se hvad kantinen byder.
nu har jeg fundet ud af det, det virker sådan set fint, men skulle også gerne have de første 2 tal med ud også, altså "100000" 20000 da det ene er et id og det andet et timestamp
for at det ikke skal være løgn ser det faktisk ud til at de eneste tal jeg skal bruge er de 2 foran, resten er urelevant, skruer lige lidt point extra på for dit besvær
Arrrgh.. Skidt, faktisk gav det mig en nørdet tilfredsstillelse at skulle brygge den afsluttende testkode sammen:
for i := 0 to Data.Count - 1 do begin mLog.Lines.Add(format('%s %d',[Data[i].Field1,Data[i].Field2])); for j := 0 to Data[i].Count - 1 do for k := 0 to Data[i][j].Count - 1 do mLog.Lines.Add(Data[i][j][k]); end;
Det her med en tredimensionel liste var sjov at lave
et lille tillægsspørgsmål hvis jeg har en streng der siger 111901111 hvordan får jeg så erstattet 90 med det er står i strengen otherstr uden at røre resten af strengen, kan det gøres nemt eller skal man til at klippe klistre?
hm.. ligemeget hvad jeg gør får jeg en accessviolation, kan jeg ikke få dig til at lave et eksempel der smider det ud i en memo? kun de 2 felter, men gerne i hver deres felt
TSegmentData = class private fID : string; fTimeStamp : integer; public constructor Create(const aString : string); property ID : string read fID1; property TimeStamp : integer read fTimeStamp; end;
implementation
{ TDataList }
type TStringStates = (ssHeader, ssSegment);
constructor TDataList.Create(const aFileName: string); var fp : TextFile; st : string; StringState : TStringStates; SegmentData : TSegmentData; begin inherited Create(true); fFileName := aFileName; SegmentData := nil;
assignfile(fp,fFileName); reset(fp); try StringState := ssHeader; while not eof(fp) do begin readln(fp,st); st := trim(st); if st <> '' then case StringState of ssHeader : begin SegmentData := TSegmentData.Create(st); if pos('{',st) > 0 then StringState := ssSegment; end; ssSegment : if st = '}' then begin if not assigned(SegmentData) then raise Exception.Create('Error in file structure'); Add(SegmentData); // Add finished record object to list StringState := ssHeader; end; end; // case end; finally closefile(fp); end; end;
function TDataList.GetSegmentData(const aIndex: integer): TSegmentData; begin result := TSegmentData(inherited Items[aIndex]); end;
{ TSegmentData }
constructor TSegmentData.Create(const aString: string); var p1,p2 : integer; begin inherited Create(true); p1 := pos(',',aString); if p1 > 0 then begin fID := copy(aString,2,p1-3); p2 := pos('{',aString); if p2 = 0 then fTimeStamp := StrToInt(trim(copy(aString,p1+1,MaxInt))) else fTimeStamp := StrToInt(trim(copy(aString,p1+1,p2-p1-1))); end; end;
Koden der smækker det over i Memoen (mLog):
procedure TfrmMain.Button1Click(Sender: TObject); var Data : TDataList; i,j : integer; begin Data := TDataList.Create('test.txt'); try mLog.Lines.Clear; for i := 0 to Data.Count - 1 do with Data[i] do mLog.Lines.Add(format('%s %d',[ID,TimeStamp])); finally Data.Free; end; end;
ad. 1: Ret stavefejlen fID1 til fID - den var nem, ikke? ad. 2: Lidt mere speciel. Vi nedarver ikke længere fra TObjectList (da du ikke ville have det skrammel med) men fra TObject og så er inherited Create anderledes. Løsning: Slet "(true)"
Jeg synes efterhånden min tålmodighed bliver sat på lidt af en prøve...
Min første tanke: Hvorfor prøver du ikke at debugge programmet med Breakpoints (F5), Wathces (Ctrl-F5) samt F7 og F8-tasterne? Delphi har nok markedets bedste debugging-faciliteter - og de er lette at bruge.
Den anden tanke: Enten er filspecifikationen, den du beskrev øverst i dette spørgsmål, forkert, eller så laver du en anden fejl jeg ikke kender til. Det er dødsimpelt det her og min testfil indlæses aldeles problemfrit - både med version 1 og 2. Prøv at undersøge det.
Undskyld at jeg nu lyder bøs, men det er altså misbrug af min tid, når du ikke selv prøver at roder med problemet.
du må undskylde jeg spørger lidt dumt igen, men jeg kan godt se hvordan du smider data ind i tsegmentdata, men har du noget docs til hvordan jeg får det ud igen, har læst koden igennem mange gange, uden held for at finde ud af hvordan det kan være at jeg kun får nuller ud
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.