Array of const / string / integers er ikke til store mængder data. De er beregnet til at føre et valgfrit antal parametre over i en procedure, eksempelvis format('',[]). At du bruger konstruktionen til store dataklumper fortæller om en forkert løsning. Der findes lister såsom TList, TObject, TCollectionList (TCollectionItem) som er meget lette at bruge - og hurtigere.
Den bedste løsning er dog nok at benytte TClientDataSet, der er en tabel i hukommelsen. Det er nok den letteste løsning da den kræver meget lidt programmering - men en smule læsning før man forstår hvordan det hænger sammen. Kan i øvrigt indlæse/gemme data i XML-format.
Hej igen. Du hjalp også i høj grad sidst, hvor du forklarede det med at bruge klasser.
Nu har jeg rodet med at få bygget en "variabel container" og et "variabel arkiv", som i første omgang var bygget på tStringList, men så ændret til arrays for at prøve at opnå mere hastighed især. Nu siger du så at det ikke er den rigtige løsning. Bør jeg så lave det tilbage til stringList eller bruge TClientDataSet istedet.
Jeg sender lige den ene klasse for at vise formålet
type varContainer=class procedure setVar(const varName:shortString;const theData:string); function getVar(const varName:shortString):string; function varString(containerName:shortString):string; function varList(const indicator:char;const splitter:shortString):string; function getName(const id:integer):shortString; function listNames(const splitter:shortString):string; procedure importVarList(const theList:string;const splitter:shortString); function importVarFile(const dataType:char;const fileName:string):boolean; function exportVarFile(const fileName:string):boolean; procedure setVarByCmd(const cmd:string); function importFromArchive(const archiveName:string):boolean; procedure exportToArchive(theArchive:varArchive;const dataName:shortString); procedure clearFocus; procedure clear; function focusVar(const varName:shortString):boolean; function focusWhere(const paramName,matchValue:shortString):boolean; function lookAt(const paramName:shortString):string; function focusAndLookAt(const varName,paramName:shortString):string; private lastParamQuest:shortString; public varNames:tShortStringArray; //navne varData:tStringArray; //data changed:boolean; curFileName:string; curDataType:char; varFocusNames:tShortStringArray; varFocusData:tStringArray; varCount,varFocusCount:integer; focusedVar:shortString; end;
De her funktioner kan så arbejde med tre forskellige datatyper TYPE A: SINGLE PARAMETER:VALUE (PER LINE) (adskilt med linieskift) TYPE B: MULTIPLE $VAR=PARAM (PER LINE) (adskilt med ;) (2 niveauer) TYPE C: SINGLE VALUE (PER LINE) (adskilt med linieskift)
Håber det giver mening. (de her strings kan i hvert fald blive lange hehe)
ok, det kunne godt se ud til at TClientDataset er en god løsning. Det vil dog tage lidt tid at afprøve det ordentligt, men jeg vil gerne give pointene, for det ser ud til at være godt ramt. (send lige et svar)
2 gb - windows xp ( ca. 500-600 mb ) - div - din exe fil = ca 900mb, det er nok ikke helt ved siden af at det er brugt op, mange små strings giver ligesom på din disk ( mange små filer ) en fragmenteret ram :) ( med mere eller mindre spild )
Der findes nogle "hack" som får windows til at smide det væk den ikke bruger, men klø på med TClientDataset, det er helt klart vejen frem, også til alle mulige andre prg.
Ok, havde ikke lige tænkt på ram også kunne være fragmenterede. Det er heller ikke fordi jeg skal bruge så meget hukommelse i dette projekt. maks 200mb måske. Under alle omstændigheder er de 400-900mb bedre end de 6mb i array.
Nu har jeg skrevet det her projekt om til at bruge stringlist som før, og det virker helt klart bedre med større mængder data. Glæder mig til at få kendskab til TClientDataset, men lige nu var det jeg havde mest brug for at vide, at det var en forkert løsning med array of string. (og at stringlist'en gør det bedre)
Hvis du skal forbi grænserne af en TStringList må du over i TObjectList. Hvert objekt du putter i den, er en selvstændig klump som ikke behøver ligge i samme klump hukommelse.
Eller naturligvis bruge TClientDataSet. Det kan være lidt forvirrende at den kan to ting: Enten fungere som en ram-baseret tabel i dit program, eller som en buffer til en database. Den kan begge og fungerer næsten som en TTable.
MartinLind: Fylder din Windows XP 900Mb? Det er ikke en Vista?. Min XP bruger 256Mb.
Hvad nu hvis man gerne vil benytte sig af en slags "shortstring"list, eller en lang liste af sin egen type, måske "string[5]" som list. Det var her jeg troede man skulle bruge "array of string[5]" eller "array of stortstring". Er det så stadigvæk clientDataSet, hvis det kun er een liste ?
En XP-pro på et netværk med div drv. og virus-chk osv. skal helt ha min. 1gb for at køre nogenlunde og hvis du koder delphi skal du brug min. 1gb mere for at køre ordenligt, da delphi ide'en bruger en del :)
Nej du skal bruge en TList til en sådan liste, en TList er et array of pointere, så den kan indeholde alt hvad du har hukommelse til, det med de 6mb du løb ind i kunne også godt være fordi din var blev alloceret på stacken og ikke heapen.
Men du skal kigge på TList, TStringList, og de andre "TList" classer delphi har, de er ret gode til mange std. ting jeg har selv brugt dem til alt lige siden D1 ( 12 år ) Et TClientDataset er mest beregnet til noget hvor du har en Database :)
Nej 2 gb ram er jo i virkeligheden ikke for meget, nu om stunder :) Jeg vil helt sikkert se nærmere på listerne. Kan godt lide sammenhængen mellem dem jeg kender i forvejen, stringlist, (memo og listbox) osv.
Det med pointere er nyt. Jeg har læst lidt om det de seneste dage i forbindelse med de array. Jeg var ikke klar over at det betød så meget omkring "hvordan" man smider ting og sager i hukommelsen. Så længe man bare kan bruge listerne, er det da okay.
Og forskellen på stack og heap er jeg også ubekendt med. Har vidst mødt et par "Stack overflow" en gang imellem :)
Hvis du bruger short strings så allokerer du altid den længde du definerer, en string[30] fylder 31 karakterer uanset om der står noget i den eller ej. Den skal du ikke bruge.
Du bør foretrække TObjectList fremfor TList da sidstnævnte: 1. Bruger pointere. Det giver usikker kode 2. Den frigiver ikke objekterne automatisk hvis man rydder listen
Hvis du laver en dataklasse og propper den i en TObjectList så bliver de alle frigivet igen når du Free'er listen - helt automatisk. Desuden er den mere sikker da den indeholder objekter i stedet for pointere (at det helt grundlæggende er en og samme ting - er en anden sag).
hrc> Er det galt opfattet at shortString er bedre at bruge end string[255]
Jeg kunne se via google, at man kan putte tStringList'erne ind i TObjectList'en.
I det variabel-arkiv projekt jeg har gang i, er der P.T. 3 stringList, med masser af "spildplads" (Nu er der ikke nogle char/shortStrings eller noget):
archiveTypes,//Bruger en hel stringList, men der er kun 1 bogstav pr linje/string :) archiveNames,//Det her er maks 50 pr linje, men bruger igen en hel stringlist archive //Det her er hele "tekstfiler" på "1 linje", adskilt med paragraf "§" :tStringList;//---- altså rigtig lange strings.
Kan i give et eksempel på hvordan dette laves bedre med TList/TObjectList, således at det virker med noget ala char/string[1], shortString, string ?
Jeg vil gerne forstå det her med shortString ordentligt. Hvis nu man har en string som altid er mellem 0 og 5 bogst. Skal man så bruge string[5] eller shortString (op til 255)
Mig bekendt er shortstring netop at du angiver længden (st: string[100])... men jeg kan tage fejl - tror dog ikke det er tilfældet her. Bruger du string (st: string) uden at angive længde, tager du fat i en skjult strengklasse der allokerer den mængde ram der er behov; helt op til 2GB. Medmindre al data du behandler har samme længde, er der ingen grund til at bruge shortstrings.
Glem i øvrigt TListen; den er til pointere og den slags bruges ikke længere. TObjectList er smartere, især hvis du laver en data-baseklasse og nedarver den til hhv. archivetype, archivename og archive. Så kan du have specialiserede klasser til dine data og en liste der kan indeholde alle typerne. Skal se om jeg kan brygge lidt sammen til dig.
Borlands VCL navnet på Borlands indpakning af det win32 API (Application Program(ming?) interface) som Microsoft stiller til rådighed - og som udgør vores adgang til Windows. De har lavet store (monstrøse) dll-biblioteker der indeholder knapper, listbokse og alt sådan noget, men det kaldes med pointere og helst med C eller C++ (og hvem gider det i dag?). det er ikke objektorienteret. Det pakkede Borland, med Anders Hejlsberg i spidsen, ind i noget Object Pascal og byggede derefter et velfungerende udviklingsmiljø ovenpå. Viola Delphi var født.
Shortstring passer med en byte.. (255) Begyndte egentlig med at bruge shortstring fordi jeg var i tvivl om hvis man sagde string[10] eller string[1],- om så den kunne have en længde på 0 (eller under det man satte den til). Men det kunne den jo så ifølge en lille test:) Når der ikke er ulemper ved bare at bruge string, kan det være man bare skal gøre det i stedet.
Det kunne være rart at komme i gang med at bruge de rigtige værktøjer, i stedet for at lave en masse forkert kode :) Vil meget gerne se mere omkring TObjectList
For ca en måned siden kom jeg ind på en side (mener det var delphi.about.com), hvor jeg første gang kunne se lidt om, hvad windows api er, og jeg kan godt se hvad du mener. Det ser ud til at størstedelen af de fleste programmer i virkeligheden er en del af windows. Synes dog det er lidt svært at komme ind på det helt konkret, med alle de $tal værdier for de forskellige muligheder osv.
Hvis man godt kan lide Microsoft og Bill Gates, så kan jeg anbefale et par gode lange videoer, hvor der holdes foredrag om eksempelvis Office Development. Første gang var jeg lige nødt til at holde en pause efter 20 minutter :) http://www.microsoft.com/events/executives/billgates.mspx
Jep, type A bruger jeg som indtillinger. Hvis der er brug for flere grupper af indstillinger, kan jeg nu oprette en varibel med klassen til hver gruppe. Fks cfgCommon,cfgLocal,cfgFont:varContainer; Derefter .create i initialization og .free i finalization :-)
Jeg bruger det i mange sammenhænge, primært som indstillinger / lister over data. Fks landekoder med forskelligt antal info pr land. Eller blot en filliste med navn på hver fil.. Alt det her forudsætter jo så, at man replace'er §$; med noget andet på forhånd.
{Type A} // fks. indstillinger for font (eller noget andet) font.name:Tahoma font.size:10 font.align:center ...
{Type B} // fks. fejlsystem (liste over fejlkoder) $empty_param:icon=doc_error;title_us=Empty parameter;title_dk=Tom parameter $empty_folder:icon=doc_error;title_us=Folder is empty;title_dk=Mappen er tom $invalid_password:title_us=Invalid password;title_dk=Ugyldig adgangskode;desc_us=.. $undefined_data:title_us=Undefined data;title_dk=Udefineret data;desc_us=..
Nu er det så at linjeskiftet erstattes med "§" : $empty_param:icon=doc_error;title_us=Empty parameter;title_dk=Tom parameter§$empty_folder:icon=doc_error;title_us=Folder is empty;title_dk=Mappen er tom§$invalid_password:title_us=Invalid password;title_dk=Ugyldig adgangskode;desc_us=..§$undefined_data:title_us=Undefined data;title_dk=Udefineret data;desc_us=..§
På den måde kan det gives et "navn" så det starter med: §B@errorcodes:$empty_param:icon=.....§$empty_folder:icon=.....§$invalid_password:icon=..... §B@logcodes:$start_app:icon=.....§ §A@fonts:font.name:Tahoma§
Herefter er det så noget i den stil: for i:=0 to count-1 do begin s:=strings[i]; if s<>'' then //beskyt kald af første tegn if s[1]='§' then //kald første tegn if s[3]='@' then begin //kald tredje tegn dataType:=s[2]; //find datatype fra andet tegn c:=ansiPos(':',s); //find første kolon dataName:=copy(s,4,c-1); //datanavn fra @ indtil kolon'et dataParams:=copy(s,c+1,length(s)) //parametrene er så efter kolon'et end end;
Nu kan man sige focus(navn) // ligesom "select". Så splitter den parametrene ved § til to lister (names,params:stringList) (først var det jeg brugte: names:array of shortString;params:array of string)
Herefter lookAt(parameter) for i:=0 to count-1 //og så hvis names[i]=parameter then begin result:=params[i];exit end
------------------------------------
Jeg kan evt sende et langt fra færdigt forsøg med en lille editor test. Men det er sikkert noget være fusker-kode :)
Der ligger selve den unit med disse to klasser. Jeg kan lave en datafil med alle typerne og smide med.
De fleste af de componenter VCL'en har bruger en TList/StringList til et eller andet, feks. Lines i en memo, item i en combobox osv.
TList er et array af pointer en pointer er samme størelse som en integer/char så hvis du har en liste af Interger/char kan du bruge en TList i stedet for tstringlist
Martin: I Objektorienteret programmering er der ikke noget der hedder pointere (det bør der i alt fald ikke være) og derfor skal man også prøve at undgå TListen. Især når dens næsten identiske fætter hedder TObjectList. De eneste (ret vigtige) forskelle er at data er typesikret og at de automatisk frigives når listen bliver det.
mbsnet: Efter at have kigget på din seneste kommentar melder spørgsmålene sig: - Hvordan ser type C ud? Har et bud, men du glemte den. - Hvorfor ikke bruge XML? Fylder det for meget? - Kreerer du virkelig n antal objekter i starten af dit program, objekter som du først frigiver ved afslutning? Det er ikke sund programmering.
Type C er korrekt. værdi1 værdi2 værdi3 altså: værdi1§værdi2§værdi3
Det er kun hvis jeg har brug for indstillingerne hele tiden. mens programmet kører. Andre gange opretter/frigiver jeg "med det samme" inden i funktionerne / procedurerne. Kender ikke rigtig xml. Men jeg kan godt lide disse 3 typer. Mange ini-filer er jo eksempelvis "type a"
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.