Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 18258
  • Last Modified:

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
0
lukeMH
Asked:
lukeMH
1 Solution
 
pritaeasSoftware EngineerCommented:
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
0
 
Russell LibbySoftware Engineer, Advisory Commented:

Simple example. Notice the use of the first element of the byte array, otherwise the dynamic array will get clobbered.

Regards,
Russell

type
  TByteArray  =  Array of Byte;

function StreamToByteArray(Stream: TStream): TByteArray;
begin

  // Check stream
  if Assigned(Stream) then
  begin
     // Reset stream position
     Stream.Position:=0;
     // Allocate size
     SetLength(result, Stream.Size);
     // Read contents of stream
     Stream.Read(result[0], Stream.Size);
  end
  else
     // Clear result
     SetLength(result, 0);

end;

procedure TForm1.Button1Click(Sender: TObject);
var  bytes:      TByteArray;
     strmMem:    TMemoryStream;
     lpBytes:    Array [0..100] of Byte;
     dwIndex:    Integer;
begin

  for dwIndex:=0 to 100 do lpBytes[dwIndex]:=dwIndex;

  strmMem:=TMemoryStream.Create;
  strmMem.Write(lpBytes, SizeOf(lpBytes));

  bytes:=StreamToByteArray(strmMem);

  if CompareMem(bytes, @lpBytes, 100) then
     ShowMessage('Success')
  else
     ShowMessage('Failure');

  strmMem.Free;

end;

0
 
lukeMHAuthor Commented:
Where do i put

type
  TByteArray  =  Array of Byte;

?

Thanks

Luke
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
Russell LibbySoftware Engineer, Advisory Commented:

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


0
 
lukeMHAuthor Commented:
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
0
 
Russell LibbySoftware Engineer, Advisory Commented:

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

0
 
lukeMHAuthor Commented:
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
0
 
BlackTigerXCommented:
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
0
 
lukeMHAuthor Commented:
rllibby you've got it,

Thanks everyone else for your comments

Kind Regards

Luke
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now