Avatar billede mukke Nybegynder
09. juli 1999 - 20:35 Der er 9 kommentarer og
1 løsning

100 points: Effektiv måde at indlæse en STOR fil til en streng

Jeg forsøger at indlæse hele indholdet af en fil der meget vel kan være større end en mb til en variabel af typen string. Filen kan indeholde null-værdier (#0) som skal behandles som alle andre værdier. (Dvs almindelige null-terminerede datatyper som PChar dur IKKE)

I det følgende er Data og TempStr begge af typen String og Buffer er et array med 65536 elementer af typen char.
Problemmet er at i takt med at Data bliver længere og længere bliver det langsomere og langsomere. (Dvs. første 20 % tager måske 2 sekunder, næste 20% tager så måske 5 sekunder....)

repeat
    BlockRead(InFile, Buffer, 65536, ActualRead);
    TempStr := '''';
    For B := 0 to ActualRead-1 do
    begin
      TempStr := TempStr + Buffer[B]
    end;
    Data := Data + TempStr;
    Inc(Stat1, ActualRead);
until eof(InFile);

Er der nogen der kan give en god måde at indlæse HELE filen til Data på een gang. Jeg har nemlig en teori om at Data bliver fragmenteret pga de mange omgange den bliver opbygget over.
Avatar billede swjensen Nybegynder
10. juli 1999 - 11:55 #1
Hvad skal Data bruges til, når du har indlæst filen? Skal den bare gemmes som noget andet, eller skal der læses og ændres i strengen?
Avatar billede swjensen Nybegynder
10. juli 1999 - 16:03 #2
Her er et forslag med StreamObjects.
Hvis du prøver at aflæse DataString, får du kun tekst ud frem til den første #0, men den indeholder hele filen alligevel. Med Position og ReadString, kan du manøvrere rundt i strengen.


procedure TForm1.Button1Click(Sender: TObject);
var MinFil:TFileStream;
var MinMemStream:TMemoryStream;
var MinStringStream:TStringStream;
var streng:string;

begin
    MinFil:=TFileStream.Create('c:\kjempefil.bin',fmOpenRead);
    MinMemStream:=TMemoryStream.Create;
    MinStringStream:=TStringStream.Create(streng);
    MinMemStream.LoadFromStream (MinFil);
    MinStringStream.CopyFrom(MinMemStream,MinMemStream.Size);
    // gør et eller andet med MinStringStream.DataString;
    // gør et eller andet med MinStringStream.Position;
    // gør et eller andet med MinStringStream.ReadString;
    // gør et eller andet med MinStringStream.WriteString;
    showmessage (IntToStr(length(MinStringStream.DataString)));
    MinStringStream.Free;
    MinMemStream.Free;
    MinFil.Free;
end;

P.S. Nu skriver du godtnok 100pt, men du er noteret for 0.
Avatar billede mukke Nybegynder
10. juli 1999 - 19:25 #3
Mange tak for forslaget - jeg har ikke lige tid til at kigge på det nu her - så du skal nok ikke forvente en dom inden i morgen :)

Grunden til jeg har sat den til 0 points er at hvis den ikke blev besvaret vill jeg ikke have mistet nogle points. Hvis jeg får noget der kan bruges skal vedkommende nok få sine points :)

Oh ja - jeg bruger copy til at snuppe korte delstrenge (der også kan indeholde #0 :) fra det store hele - og dette i stor stil.
Avatar billede swjensen Nybegynder
10. juli 1999 - 20:11 #4
OK - copy kan anvendes på MinStringStream.DataString
Avatar billede mukke Nybegynder
10. juli 1999 - 21:56 #5
TAK!!!

Det virker genialt godt.

Jeg springer godt nok et led over idet jeg kopiererer direkte fra FileStream til StringStream. Herefter bruger jeg så
Data := StringStream.DataString
til at få det hele til at være som jeg plejer at have det :)
Og som sagt - det fungerer præcis sådan som jeg håbede på.

Efter at skrive dette opretter jeg et ekstra spørgsmål i denne katagori med 100 points til dig. Håber ikke det er til alt for meget besvær på denne måde.
Avatar billede swjensen Nybegynder
10. juli 1999 - 22:26 #6
Jeg kunne heller ikke lige greje, at jeg ikke kunne lave en StringStream.CopyFrom(FileStream) - jeg blev ved med at få en fejlmeddelelse - men nu har jeg fundet ud af det: jeg havde glemt at fjerne linien
MinMemStream.Free
Der kan man se, hvad der kommer ud af at arbejde for meget med VB - der kan man rask væk lave en
set object = nothing,
om objektet nu har været i brug eller ej.
Avatar billede mukke Nybegynder
10. juli 1999 - 23:11 #7
Kan du også i Delphi... brug destroy i stedet for free
Avatar billede mukke Nybegynder
10. juli 1999 - 23:12 #8
Hmm oops.. nu vrøvler jeg.. free skulle være sikker nok....... jf. hjælpen checker den om objectet er blevet lavet...(?)
Avatar billede swjensen Nybegynder
11. juli 1999 - 14:45 #9
Ja, du har ret. Alligevel får jeg en fejl, hvis jeg kører nedenstående.

procedure TForm1.Button1Click(Sender: TObject);
var MinFil:TFileStream;
var MinMemStream:TMemoryStream;
var MinStringStream:TStringStream;
var streng:string;

begin
    MinFil:=TFileStream.Create('c:\autoexec.bat',fmOpenRead);
    MinStringStream:=TStringStream.Create(streng);
    MinStringStream.CopyFrom(MinFil,MinFil.Size);
    MinStringStream.Free;
    MinMemStream.Free;
    MinFil.Free;
end;

Avatar billede mukke Nybegynder
11. juli 1999 - 16:48 #10
mystisk...
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester