Link to home
Start Free TrialLog in
Avatar of lukeMH
lukeMH

asked on

Copy a memory stream into a byte array

Ok here is a very simple one, but I need an answer quick please.

I have a memory stream (tmemorystream) and I need to put the contents of the memory stream into a byte array.

Here is what i tried to do but I've obviously done something wrong as it doesnt work

function TMainForm.convertTobytearray;

var
  TEncoded : String;
  SomeStream : tmemorystream;
  bufs : array of byte;

begin

//SNIP unimportant code//

  SomeStream := TMemoryStream.Create;
  SomeStream := HTTPSend(Tencoded);
  setlength(bufs,somestream.size);
  somestream.Read(bufs,somestream.size);
  showmessage(pchar(somestream.memory));
end;

If I step through the code, I see that a byte array of 6 bytes is allocated (the same as the size of the tmemorystream) but the bytes are all 00's but the memorystream contains actual binary data

I'm sure I have just missed something simple

Thanks in advance for any help

Luke
Avatar of pritaeas
pritaeas
Flag of Netherlands image

A TMemoryStream has a Buffer property which is what need. But you'll have to look at the source to see how to access it. I don't have access to Delphi for the time being.

hth, pritaeas
ASKER CERTIFIED SOLUTION
Avatar of Russell Libby
Russell Libby
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of lukeMH
lukeMH

ASKER

Where do i put

type
  TByteArray  =  Array of Byte;

?

Thanks

Luke

Define it pretty much anywhere..... just so long as it appears before usage. But please note, I only defined it so I could demo a function that returned that data type. You could just put the code inline, as in your example, and not have to define it at all, eg:

var
  TEncoded : String;
  SomeStream : tmemorystream;
  bufs : array of byte;

begin

//SNIP unimportant code//

  SomeStream := TMemoryStream.Create;
  SomeStream := HTTPSend(Tencoded);
  setlength(bufs,somestream.size);
  somestream.Read(bufs[0],somestream.size); // <- change
  showmessage(pchar(somestream.memory));
end;

The ** ONLY ** purpose of the demo was to illustrate the real problem. By passing the zero element, you are really passing the address of the first element of the array, vs the array itself. For dynamic arrays this does make a difference.


Russell


Avatar of lukeMH

ASKER

Hi,

I changed the line in my code like you suggested, but this didn't seem to do anything as buf is still an array or 0's

Kind Regards

Luke

Luke,

Did you check to make sure that the stream was reset (position:=0) before attempting the Read? A Stream.Read will read from the current position, which if at the end of the stream will read nothing.

var
  TEncoded : String;
  SomeStream : tmemorystream;
  bufs : array of byte;
  dwRead:     Integer;
begin

  SomeStream:=TMemoryStream.Create;
  SomeStream:=HTTPSend(Tencoded);
  MessageBox(0, PChar(Format('Stream size = %d, Steam Position = %d', [SomeStream.Size, SomeStream.Position])), nil, MB_OK);

  SetLength(bufs, SomeStream.size);
  SomeStream.Position:=0;
  dwRead:=SomeStream.Read(bufs[0], SomeStream.size);
  MessageBox(0, PChar(Format('Number of bytes read = %d', [dwRead])), nil, MB_OK);

  MessageBox(0, SomeStream.Memory, nil, MB_OK);

end;


Regards,
Russell

Avatar of lukeMH

ASKER

doh!

I think you may well be right there, just going to check it out and if all is well points shall be awarded to you

Thanks and regards

Luke
you can use
TByteDynArray

which is defined in the unit: Types

also beaware that TByteArray is already defined in the SysUtils unit, you wouldn't want to use that name as to not cause conflicts
Avatar of lukeMH

ASKER

rllibby you've got it,

Thanks everyone else for your comments

Kind Regards

Luke