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
相关产品推荐
相关产品推荐

