Avatar billede screwdriver Nybegynder
15. september 2004 - 10:47 Der er 10 kommentarer og
1 løsning

Stream.Read med Dynamisk array

Hej

Jeg skal læse fra en stream, men kan ikke gøre det med et dynamisk array. Kun med et statisk array. Nogen der kan hjlæpe ?

Kode:
type
    PDataArray = ^TDataArray ;
    TDataArray = array of byte ;

procedure TUdpModule.UDPRead(Sender: TObject; AData: TStream; ABinding: TIdSocketHandle);
var
  Buffer: array[0..1023] of byte;
  DataArray: PDataArray ;
  i : Integer ;
begin
  New(DataArray) ;
  SetLength( DataArray^, AData.Size ) ;

  AData.Read(Buffer, AData.Size);

  for i := 0 to AData.Size -1 do
    DataArray^[i] := Buffer[i] ;
  ...
end ;

Hvis jeg skriver:
  AData.Read(DataArray^, AData.Size);

i stedet for, kommer der ikke noget i arrayet :-)
Avatar billede martinlind Nybegynder
15. september 2004 - 10:53 #1
prøv :

AData.Read(DataArray[0], AData.Size);
eller
AData.Read(PChar(DataArray), AData.Size);
Avatar billede screwdriver Nybegynder
15. september 2004 - 12:46 #2
Jeg har nu prøvet med

AData.Read(DataArray[0], AData.Size); ... ( Kunne ikke compileres )
AData.Read(DataArray^[0], AData.Size);
AData.Read(PChar(DataArray), AData.Size);
AData.Read(PChar(DataArray^), AData.Size);

så det hjalp desværre ikke ...
Avatar billede martinlind Nybegynder
15. september 2004 - 13:04 #3
det forstår jeg ikke denne func viker

procedure PutStr(AStr: String; AStream: TStream);
VAR
  Len : Integer;
begin
  Len := Length(AStr);
  AStream.Write(Len,SizeOf(Len));
  if Len > 0 then
    AStream.Write(Astr[1],Len);  <---- skriver i princippet bare et array of byte
end;

er du sikker på at din Size er støre end 0

/Martin
Avatar billede hrc Mester
15. september 2004 - 13:13 #4
uhhh. Jeg kan ikke rigtigt lide de dynamiske arrays. Det er sikkert bare konservative mig, men er de ikke ret sløve? Hvad med at prøve at skrive

aData.Read(Buffer[0],aData.Size);

I øvrigt er der noget rod med aData.Size. Der er ingen garanti for at størrelsen holder sig under 1kb. Se eksempel hvor jeg justerer antallet af bytes i denne simple filkopiering

procedure TfrmMain.Button1Click(Sender: TObject);
var
  lgd : integer;
  iStream, oStream : TFileStream;
  Buffer : TBufferType;
begin
  lgd := sizeof(TBufferType);
  iStream := TFileStream.Create('c:\eksperten.pas',fmOpenRead);
  oStream := TFileStream.Create('c:\eksperten.out',fmCreate);
  try
    while iStream.Position < iStream.Size do begin
      if iStream.Size - iStream.Position < lgd then // EOS
        lgd := iStream.Size - iStream.Position;
      iStream.ReadBuffer(Buffer[0],lgd);
      oStream.WriteBuffer(Buffer[0],lgd);
    end;
  finally
    iStream.Free;
    oStream.Free;
  end;
end;
Avatar billede jan_h Nybegynder
16. september 2004 - 12:51 #5
Hvad er det man checker på når man skriver "if iStream.Size - iStream.Position < lgd then" ??? Altså forstår ikke hvad der menes med size og position men jeg har så heller ikke forstand på streaming :/ kunne godt tænke mig et par tutorials i den sammenhæng...
Avatar billede martinlind Nybegynder
16. september 2004 - 12:57 #6
du kan evt. forestille dig at en stream er en lang række af byte, din pos er hvor i rækken du står og size er hvor lang rækken er.
Avatar billede hrc Mester
16. september 2004 - 13:00 #7
I realiteten tjekker jeg om der er End Of Stream. Position er TStreams svar på seek() og indikerer hvor langt man er i læsning af streamen.

I ovenstående (og der er sikkert mere elegante løsninger) tjekker jeg om der er nok data i streamen til at læse 1 kb over i bufferen. Hvis der er mindre, så nøjes jeg med det (ensbetydende at man har nået End Of Stream)

Konceptet streaming kunne godt indikere at der ikke var en ende på data, men det er der og størrelsen kan findes via Size-propertyen.
Avatar billede hrc Mester
16. september 2004 - 13:07 #8
Den store fordel med streaming kontra "assignfile/reset/rewrite/closefile" er, at man kan nedarve fra et baseobjekt.

Det betyder at det er lige meget om data kommer fra en TMemorystream eller en TFileStream eller noget helt tredie. De nedarver alle fra TStream og har alle de samme attributter/metoder (eng: properties/methods).

Ulempen er tekstfiler der læses linie for linie. De er noget sværere at læse med en stream. Der findes godtnok en TStringStream, men enten har jeg ikke fundet ud af hvordan den virker eller så virker den bare ikke til formålet.
Avatar billede martinlind Nybegynder
16. september 2004 - 13:11 #9
Mht. TextFiler så brug en StringList.LoadFromFile, hurtigt nemt og smart :)
Avatar billede screwdriver Nybegynder
21. september 2004 - 08:40 #10
MartinLind: Jeg har prøvet at teste din func, men kan ikke få den til at virke. Jeg går ud fra at det er fordi jeg creater AStream forkert ? jeg får en "Abstract Error", ved linien:  AStream.Write(Len,SizeOf(Len));

procedure TForm1.Button3Click(Sender: TObject);
Var
  AStream : TStream ;
  Len : Integer;
  AStr, BStr : String ;
begin
  AStream := TStream.Create ;

  AStr := 'Test' ;
  Len := Length(AStr);

  AStream.Write(Len,SizeOf(Len));
  if Len > 0 then
    AStream.Write(Astr[1],Len); //  <---- skriver i princippet bare et array of byte
  AStream.Read(Bstr[1], Len);
  Label8.Caption := BStr ;

hrc:
det er en smart måde at læse på, og jeg vil også bruge den, hvis jeg ikke kan få det til at virke med dynamiske arrays. Jeg bruger arrayet til at kalde en anden funktion, som skal kaldes med et Array, med den længde som Streamen har, så hvis jeg læser det ind i et statisk array, bliver jeg alligevel nød til at lægge det over i et dynamisk, for at få den rigtige længde på arrayet :-)
Avatar billede screwdriver Nybegynder
18. oktober 2004 - 12:46 #11
Her er ikke kommet nogle kommentarer, svar længe så jeg lukker spørgsmålet
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