带有附加字符串的文件的 TMemoryStream

TMemoryStream of a file with a string attached to it

我有一个图片的 TMemoryStream,但我想在该 TMemoryStream 中添加一个 String 来定义该图片的内容,然后分别读取它们。

TMemoryStream 将从 IdTCPclient 发送到 IdTCPserver,服务器将读取字符串然后是图片。 如果字符串位于流的开头,则 id 更喜欢。
第一次遇到内存流里面有多个日期,请赐教

//编辑:根据 MBo Answer 添加当前代码

procedure TForm1.Button1Click(Sender: TObject);
   var
   s: string;
   bm: TBitmap;
   ms ,ms1: TMemoryStream;
   len: Int64;
   JPEGImage: TJPEGImage;
begin
 IdTCPClient1.Connect;
 begin
     ms:=TMemoryStream.Create;
     ms1:=TMemoryStream.Create;
     JPEGImage := TJPEGImage.Create;

        s := 'A nice picture';
        ms:=CapScreen(100); //function result in memory stream

        len := Length(s) * SizeOf(Char);
        ms1.Write(len, SizeOf(len));
        ms1.Write(PChar(s)^, len);
        ms1.copyfrom(ms,ms.Size) ;         //    <-- stream read error
        ms1.Position := 0;
        Caption := s;
        JPEGImage.LoadFromStream(ms1);
        Image1.Picture.Assign(JPEGImage);
    end;

    IdTCPClient1.IOHandler.Write(ms1, 0, True);
    ms.Free;
    ms1.Free;
    JPEGImage.Free;
 end;

从一个简单的例子开始。图片从磁盘载入此处

var
  s: string;
  bm: TBitmap;
  ms: TMemoryStream;
  len: Int64;
begin
  ms := TMemoryStream.Create;
  bm := TBitmap.Create;
  try
    bm.LoadFromFile('d:\d.bmp');
    //write string body size, body itself
    s := 'A nice picture';
    len := Length(s) * SizeOf(Char);
    ms.Write(len, SizeOf(len));
    ms.Write(PChar(s)^, len);

    //now picture
    bm.SaveToStream(ms);

    //change string and picture to be sure we load new ones
    bm.Canvas.FillRect(rect(0,0,100,100));
    s := '';

    //now restore and show
    ms.Position := 0;
    ms.Read(len, sizeof(len));
    SetLength(s, len div SizeOf(Char));
    ms.Read(PChar(s)^, len);
    Caption := s;
    bm.LoadFromStream(ms); //reads picture from current position
    Canvas.Draw(0, 0, bm);
  finally
    ms.Free;
    bm.Free;
  end;

从另一个流加载的 jpeg 示例:

var
  s: string;
  ms, jpstream: TMemoryStream;
  len: Int64;
  jp: TJpegImage;
begin
  ms := TMemoryStream.Create;
  jpstream := TMemoryStream.Create;
  jp := TJpegImage.Create;


  try
    //write string body size, body itself
    s := 'A nice picture';
    len := Length(s) * SizeOf(Char);
    ms.Write(len, SizeOf(len));
    ms.Write(PChar(s)^, len);

    jpstream.LoadFromFile('d:\d.jpg');
    jpstream.Position := 0;
    ms.CopyFrom(jpstream, jpstream.Size);


    //now restore ans show
    ms.Position := 0;
    ms.Read(len, sizeof(len));
    SetLength(s, len div SizeOf(Char));
    ms.Read(PChar(s)^, len);
    Caption := s;

    jp.LoadFromStream(ms);

    Canvas.Draw(0, 0, jp);
  finally
    ms.Free;
    jp.Free;
    jpstream.Free;
  end;