Den først var rigtig. Er at betragte som tre kolonner x,y,z: Altså: pkt[i].x bliver 3432 første gang og 3453 anden gang og pkt[i].z bliver 45 første gang og 76 anden gang
>>Hermandsen, Ja, Mellemrum adskiller de tre 'kolonner'. Data er geografiske koordinater: x,y og en højde z adskildt af mellemrum. En koordinat (pkt) i hver linie i ASCII filen.
procedure TForm1.Button1Click(Sender: TObject); function GetToken(var aStr : String; const Delimiter : Char = #32) : Integer; var i : Integer; begin i := pos(Delimiter, aStr); if i = 0 then Result := StrToInt(aStr) else Result := StrToInt(copy(aStr, 1, i-1)); Delete(aStr, 1, i); end;
var PlysHest : TPlysHest; i : Integer; s : String; begin for i := 0 to StringList.Count -1 do begin s := StringList[i]; PlysHest.x := GetToken(s); PlysHest.y := GetToken(s); PlysHest.z := GetToken(s); end; end;
type T3DPoint = record x: Single; y: Single; z: Single; end;
function ReadFile(S : String) : array[0..100] of T3DPoint; var F : TextFile; Data : Char; RData : String; i, iCount : Integer; P : array[0..100] of T3DPoint; begin if FileExists(S) then begin i := 0; iCount := 0; try AssignFile(F,S); Reset(F); while not eOf(F) do begin Read(F,Data);
if (Data in [Chr(32)..Chr(255)]) then begin if Data [Chr(33..Chr(255)] then RData := RData+Data else begin Inc(i,1); case i of 1: P[iCount].X := FloatToStr(RData); 2: P[iCount].Y := FloatToStr(RData); 3: begin P[iCount].Z := FloatToStr(RData); i := 0; end; end; RData := ''; end; end else Inc(iCount,1); end; CloseFile(F); except ShowMessage('Fejl ved indlæsning af filen: '+Dir); end; end else ShowMessage('Kan ikke finde filen: '+Dir);
Result := P; end;
Jeg har ikke testet den, men noget lign. dette kunne vel sagtens bruges :-)) NB: Du kan selv ændre til Dynamic arrays, hvis dette er en fordel for dig!
zerohero>> Det er vel i højgrad en smagssag om man vil bruge en TStringList eller du vil læse en linje af gangen. Hvis du vil det brude man så ikke bruge en TReader ?
Anyway din ide med et Array bryder jeg mig ikke meget om .... Jeg ville indsætte indsætte mine data i en binært træ, eller i det mindste blot en TList ligende dims ... Den er meget hurtigere at søge i.
Oups, jeg ser lige at der forresten også skulle et T foran min 3DPoint-record... Typer må jo ikke stare med tal! ;)
>>zerohero Hvorfor bruger du egentlig P? Udskift den med Result, så sparer du en 2 linier kode og 201 records af 4 bytes, altså 804 bytes hukommelse!!! ;)
zerohero >> at læse det hele ind i en TStringList er også MEGET hurtigere end at læse EN line adgangen, en TStringList er hamrende hurtig til at læse data ind i forhold til en std. TextFile
>>erniez13 30000% hastighedsoptimering = hvorfor få resultater i dag når man kunne have fået det i går. Den kode vil jeg også gerne se. 30000procenthvorvildt@lanstorp.com
Hehe, såså, 30000% er nok lidt overdrevet (Det er ikke sådan så den kan skrue tiden tilbage eller noget - Men det kunne være fedt! :P) , men ihvertfald en fordobling af hastigheden kan man godt forvente... Den kode jeg har egner sig ikke helt til spørgsmålet her, så jeg skal lige omskrive den en lille smule når jeg får tid, jeg skal nok poste den her i løbet af ugen til jer! ;)
procedure TForm1.Button1Click(Sender: TObject); var FileStream : TFileStream; i : Integer; HesteRecord : THesteRecord; Writer : TMyWriter; begin FileStream := TFileStream.Create('C:\Hest.txt', fmCreate); Writer := TMyWriter.Create(FileStream, $FF); Writer.WriteListBegin;
for i := 0 to 10 do begin HesteRecord.S := IntToStr(i); Writer.WriteHesteRecord(HesteRecord); end; Writer.WriteListEnd; Writer.Destroy; FreeandNil(FileStream); end;
procedure TForm1.Button2Click(Sender: TObject); var FileStream : TFileStream; HesteRecord : THesteRecord; Reader : TMyReader; begin FileStream := TFileStream.Create('C:\Hest.txt', fmOpenRead or fmShareDenyWrite); Reader := TMyReader.Create(FileStream, $FF); Reader.ReadListBegin;
while not Reader.EndOfList do begin Reader.ReadHesteRecord(HesteRecord); Memo1.Lines.Add(HesteRecord.S); end;
Hvis du bare kalder .Free på et object så beholder Object Referencen sin værdi. Selv om Objectet er frigivet. Det kan give problemer hvis du længere nede i din kode bruger If assigned(....). Derfor har Borland i D5 indført en Procedure der hedder FreeAndNil. Den Free Objecter OG sætter Obj Referencen til Nil.
Altså :
var Hest : TObject; begin Hest := TObject.Create; Hest.Free; If Assigned(Hest) then ShowMessage('');
Hest := TObject.Create; FreeAndNil(Hest); If Assigned(Hest) then ShowMessage(''); end;
Use FreeAndNil to ensure that a variable is nil after you free the object it references. Pass any variable that represents an object as the Obj parameter.
Warning: Do not pass a value for Obj if it is not an instance of TObject or one of its descendants.
procedure FreeAndNil(var Obj); var P: TObject; begin P := TObject(Obj); TObject(Obj) := nil; // clear the reference before destroying the object P.Free; end;
Jeg har et lidt stører og mere brugbart eksempel på Hvordan man bruger TReader og Twriter til at lave sit eget filformat... Hvis du vil have det så drop mig en mail og bed om min THorseFile
Hvis man endelig VIL bruge TReader/TWriter så er det smarteste at lave sin Record om til en Class der arver fra TPersistent og så lave sine Record-felter om til Published propertis så er alt koden nemlig lavet for dig, så kan du bare høvle det ned med en TFileStream.WriteComponent();
1) Du kommer ALDRIG til at kunne streame en klasse ned i en Fil med file of .... 2) Du Gemmer en masse tom plads. 3) Det froholder sig med TReader og TWriter kontra File of som der gør mellem procedural og Objectorienteret programmering !
Mit Sidste foreslag har den store fordel at du ikke behøver ændre i din Save/Load rutine du add'er bare nogle ny property så bliver de automatisk gemt/hentet ( jeg lavede på et tidspunkt et fuldstændigt selv tilpassende adr. kartotek, nye felt addede man bare til DataClass'en så tilpassede resten af prg. sig, grid'er osv. )
Jeg sunes den med de published properties ikke er for god ... Dels kan du kun Gemme published data, og dels synes jeg man bliver meget bunder op af et meget simpelt filformat ....
Jeg brug nedarvninger af hhv. TStream og TWriter, således de kan læse og skrive en hel record af gangen ....
Du er IKKE mere bundet en Delphi's comp. er bundet, og det er jo ikke ret meget *G*, da du kan impl. de avancerede typer som du normalt gør hvis det var en comp. du lavede, men du får resten foræret
Hvor jeg skal ha' gemt vName, vSourceDir, vDestDir, vSize og vDownloaded (de er erklæret som properties)...
Jeg har så lige prøvet at gemme ca. 300 TFile's (på min måde) i en fil... Den fylder omkring 20kb, så hvordan du har båret dig ad med at få 100000 adr. kort ned under 100kb er jeg helt sikkert meget interesseret i at vide!!! :)
7002 TFile's gemt på min måde... 0,528 sekunder (brugte bare GetTickCount, så regn ikke med præcition) 740 kb
Hmmm... Jeg tror da vist at jeg skal til at bruge din metode, Jens! :) Vil da gerne lige forsvare mig selv og sige at mange af mine strenge er lidt halv-lange... :)
Lav din class om til at arve fra TPersistent og flyt dinne property's ned til published, så kan du gemme med WriteComponent / WriteComponentRes, jeg mener jeg brugte Res udgaven for at få det til at fylde mindre
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.