Avatar billede spectual Nybegynder
09. oktober 2002 - 22:06 Der er 19 kommentarer og
1 løsning

TMemorystream

Hej.

TMemorystream class'en i delphi er svaret på mit problem med undtagelse af een ting.

Jeg har brug for at kunne læse et antal bytes fra starten af stream'en, for herefter at smide dem væk uden at skade resten af de data, der end måtte være i den stream.

Jeg er klar over, at den mulighed ikke eksisterer i forevejen, så man må nok blive nødt til at lave en ny class, der nedarver fra tmemorystream.

Kan nogen finde noget kode eller konstruere et eksempel på sådan en udvidelse?
Avatar billede borrisholt Novice
10. oktober 2002 - 08:28 #1
kan du ikke bare flytte memory pointeren ?

Jens B
Avatar billede spectual Nybegynder
10. oktober 2002 - 12:53 #2
jo - det er vist den optimale løsning.

Men det er vist ikke helt let at lave.

Man er nødt til at lave en ny klasser, der nedarver fra TMemorystream, der offentligører en MySetPointer funktion, der kalder SetPointer fra TCustomMemoryStream.

Det har jeg også fået til at virke fint nok, men når jeg prøver at frigøre den hukommelse, der nu er ledig, kommer den med en exception, EInvalidPointerOperation.

Her er min kode:


unit prg;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Edit2: TEdit;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TMemoryStream2 = class (TMemoryStream)
  public
    procedure SetMemPointer(Ptr: Pointer; Size: Longint);
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TMemoryStream2.SetMemPointer(Ptr: Pointer; Size: Longint);
begin
  SetPointer ( ptr, size );
end;

procedure TForm1.Button1Click(Sender: TObject);
var
buf : tmemorystream2;
h : string;
bufz : array [0..255] of char;

memPtr : pchar;
a : integer;

begin

buf := tmemorystream2.create;

  h := edit1.text;
  strpcopy ( bufz, h );

  buf.Write ( bufz, length (h)+1 );

  memPtr := buf.Memory;

  buf.SetMemPointer ( memPtr+4, 10 );

  showmessage ( ny [0] );

//  Move(memPtr[8], memPtr[0], buf.Size - 8);
// buf.Seek ( 0, soFromBeginning );

a := 0;repeat;bufz [a] := #0;inc (a);until (a=255);

  buf.Seek ( 0, soFromBeginning );
  a := buf.Read ( bufz, 10 );

  memo1.Lines.Add ( bufz );

end;

end.
Avatar billede spectual Nybegynder
10. oktober 2002 - 12:55 #3
(SetPointer metoden er erklæret "protected" i TCustomMemoryStream og der kan derfor ikke opnåes adgang til den i TMemoryStream.
Avatar billede borrisholt Novice
10. oktober 2002 - 12:57 #4
Mnnn .. Ja .. Det er fordi du skal gemme den gamle pointer :

  TMemoryStream2 = class (TMemoryStream)
  private
    OldPtr : Pointer;
  public
    procedure SetMemPointer(Ptr: Pointer; Size: Longint);
    destructor destroy; override;
  end;

procedure TMemoryStream2.SetMemPointer(Ptr: Pointer; Size: Longint);
begin
  OldPtr := Memory; 
  SetPointer ( ptr, size );
end;

procedure TMemoryStream2.SetMemPointer(Ptr: Pointer; Size: Longint);
begin
  OldPtr := Memory; 
  SetPointer ( ptr, size );
end;

procedure TMemoryStream2.SetMemPointer(Ptr: Pointer; Size: Longint);
begin
  OldPtr := Memory; 
  SetPointer ( ptr, size );
end;

procedure TMemoryStream2.Destroy;
begin
  SetPointer ( OldPtr, size );
end;

Sådan noget alla det .. Frit fra leveren !

Jens B
Avatar billede spectual Nybegynder
10. oktober 2002 - 12:58 #5
Øh.. jeg mener du kan ikke få lov til at kalde den metode på et objekt af typen tmemorystream, da det er en nedarvet, protected metode.
Avatar billede spectual Nybegynder
10. oktober 2002 - 13:01 #6
nå ja.. i så fald vil hukommelse først blive frigjort når objektet destrueres..

det ville være bedre at frigøre den undervejs - altså den del der bliver smidt væk.
Avatar billede spectual Nybegynder
10. oktober 2002 - 13:01 #7
det kræver vel en reallokering? reallokering = tabt data?
Avatar billede borrisholt Novice
10. oktober 2002 - 13:02 #8
hvad er det du prøver at lave ?

Så vidt jeg kan se prøver du blot at læse de 10 første bytes ind i en TMemo. Når du har kald Read har du flyttet din ReadPointer. Præcis som i en fil hvor det blot er fil pointeren du flytter ....
Avatar billede spectual Nybegynder
10. oktober 2002 - 13:04 #9
Ja.. det er ikke i den samhæng den skal bruges.

Den skal bruges til en netværks dll, der samler data ind når de modtages.

Brugeren af dll'en skulle så kunne læse f.eks. 5 kb. af det indkomne data.

Hvis man nu modtager 200 mb. kræver det ret meget hukommelse at samle data.
Avatar billede borrisholt Novice
10. oktober 2002 - 13:07 #10
Det er rigtigt så brug en TFileStream !

Jens b
Avatar billede spectual Nybegynder
10. oktober 2002 - 13:07 #11
hm..
Avatar billede spectual Nybegynder
10. oktober 2002 - 13:08 #12
det er vel i princippet det samme...
Avatar billede spectual Nybegynder
10. oktober 2002 - 13:09 #13
en tmemorystream vil vel også blive smidt på HD hvis den er for stor.
Avatar billede borrisholt Novice
10. oktober 2002 - 13:09 #14
nob ... Så har du det liggende på HD'en og læser kun det ind du beder om !

Jens B
Avatar billede borrisholt Novice
10. oktober 2002 - 13:10 #15
hov krydsende svat .. Ja den vil også blive smidt på HD'en .. Men brug en TFileStream !

Jens B
Avatar billede spectual Nybegynder
10. oktober 2002 - 13:11 #16
det er også for at undgå unødig HD aktivitet.

Jeg kunne selvfølgelig lave en TList med TMemoryStream objekter og så frigøre dem når de er blevet brugt.

Men så er jeg tilbage ved min nuværende løsning med manuelt allokerede stykker hukommelse i en TList.
Avatar billede spectual Nybegynder
10. oktober 2002 - 13:13 #17
andet del af problemet er jo også, at i een samhæng, hvor dll'en bruges, er det måske små 10 k. "pakker", den skal samle og i en anden er det måske flere GB.
Avatar billede spectual Nybegynder
10. oktober 2002 - 13:15 #18
måske min nuværende løsning ikke er så tosset endda...
Avatar billede michaelx Nybegynder
11. oktober 2002 - 13:03 #19
Jeg er helt ny her, så måske er der jeg noget jeg hat misforstået,
men når jeg ser Jens B konstruere en klasse for at løse dette problem
så bliver jeg forvirret.

Hvad er der galt med at bruge TMemoryStream.Position := ønsket offset ?

Michael X
Avatar billede spectual Nybegynder
11. oktober 2002 - 19:07 #20
Problemet er, at der vil blive optaget unødig hukommelse, hvor når dataene er læst, skal de i dette tilfælde ikke bruges længere.

Samhængen det skal bruges i er, at den skal samle data ind fra netværket asynkront, dvs. mens programmet fortsætter sin normale gang.

Hvis man forestiller sig, at man skal modtage 1 gb., er det for meget hukommelse det program skal bruge - derfor må den deallokere undervejs i takt med at dataene bliver læst.
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