如何在Delphi 10.2中更改对MemoryStream的写入?

时间:2018-11-29 08:38:24

标签: delphi memorystream delphi-10.1-berlin delphi-10.2-tokyo

我将代码从10.1移植到10.2,这给了我错误:

procedure TForm4.FormCreate(Sender: TObject);
const
  CFourBytes: array[0..3] of Byte = (1, 2, 3, 4);
var
  LStream: TMemoryStream;
  LBuffer: array of Byte;
begin
  SetLength(LBuffer, 4);
  LStream := TMemoryStream.Create;
  LStream.Write(@CFourBytes[0], 4); // E2036 Variable required

  LStream.Position := 0;
  LStream.ReadData(@LBuffer[0], 4);
end;

我必须将违规行更改为LStream.Write(CFourBytes[0], 4);

发生了什么变化?我一直都做错了吗?

2 个答案:

答案 0 :(得分:3)

您问题中的代码确实在较旧版本中进行了编译,但不应这样做。在10.2中看到的行为是正确的。

在旧版本中发生的事情非常奇怪。编译器在TStream中选择此重载:

function Write(const Buffer: TBytes; Count: Longint): Longint; overload;

这特别糟糕,因为传递给此方法的是静态数组CFourBytes的地址。绝对不是TBytes对象。

现在恰好发生了一个TBytes变量是数组第一个元素的地址。 TBytes的{​​{1}}替代中没有任何内容引用该伪造TMemoryStream.Write对象的Length()。因此,您的代码恰好按预期工作。很明显,这是一个已修复的编译器错误。

您的代码一直被破坏,直到现在,您还是幸运地摆脱了它。您应该修复您的代码。像这样:

TBytes

请注意,我使用的是LStream := TMemoryStream.Create; try LStream.WriteBuffer(CFourBytes, SizeOf(CFourBytes)); SetLength(LBuffer, LStream.Size); LStream.Position := 0; LStream.ReadBuffer(LBuffer[0], LStream.Size); finally LStream.Free; end; WriteBuffer而不是ReadBufferWrite。这些是Read首选的方法。原因是它们执行错误检查并在发生错误的情况下引发异常,这与TStreamWrite不同。

答案 1 :(得分:1)

也许什么都没有改变。

TStream.Write/Read方法始终使用未类型化的const/var参数const Bufferhelp),并且使用变量地址是错误的(因为方法(准确地说,是编译器)找到了地址)变量本身)。

可能您不小心将这些方法与使用 typed 参数且其中overloaded versions之一获得Pointer类型参数的Read / Write Data 方法混淆。

这里ReadData实现取消引用此指针,并在内部使用ReadRead依次调用Move,最后一个例程再次获取缓冲区的地址:))