You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TMemoryStream转字节数组出错,求正确实现方案

正确将TMemoryStream转换为字节数组的方法

原代码的问题分析

你的代码存在几个关键错误:

  • Data.Read(arrBytes[High(arrBytes)], Data.Size)中,第二个参数是要读取的字节数,你传入了整个流的大小,这会导致每次尝试读取全部流数据,但数组仅扩容1个元素,既会造成内存越界,也会让读取逻辑完全混乱。
  • 手动修改Data.Position完全多余,Read方法执行后会自动将Position移动到已读取字节的末尾。
  • 循环条件Data.Position >= Data.Size -1逻辑错误,正确的终止条件应该是判断Position是否到达流的总大小(Data.Position >= Data.Size)。

正确实现方式

方法1:直接利用内部缓冲区(最简便高效)

TMemoryStream的Memory属性直接指向其内部的字节缓冲区,可直接复制数据到字节数组:

var
  arrBytes: TBytes;
begin
  // 先设置数组大小与流一致
  SetLength(arrBytes, Data.Size);
  if Data.Size > 0 then
    // 直接复制流缓冲区的内容到数组
    Move(Data.Memory^, arrBytes[0], Data.Size);
  // 可选:重置流的位置到起始处
  Data.Position := 0;
end;

方法2:用Read一次性读取所有数据

如果不想直接操作内部缓冲区,可通过Read方法一次性读取全部数据:

var
  arrBytes: TBytes;
begin
  // 先将流位置重置到起始处
  Data.Position := 0;
  // 设置数组大小匹配流的总字节数
  SetLength(arrBytes, Data.Size);
  if Data.Size > 0 then
    // 一次性读取所有数据到数组
    Data.Read(arrBytes[0], Data.Size);
end;

方法3:循环读取单个字节(适合理解原理)

如果需要通过循环逐字节读取,正确的写法如下(无需手动调整Position):

var
  arrBytes: TBytes;
  b: Byte;
begin
  Data.Position := 0;
  SetLength(arrBytes, 0);
  // 当流位置未到达末尾时循环
  while Data.Position < Data.Size do
  begin
    // 读取1个字节
    Data.Read(b, 1);
    // 扩容数组并赋值
    SetLength(arrBytes, Length(arrBytes) + 1);
    arrBytes[High(arrBytes)] := b;
  end;
end;

内容的提问来源于stack exchange,提问作者Adriaan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 10:50:37