我正在编写一个使用Delphi2010对字节序列进行Z85Encoding的过程。所以我写了一个函数:
function Z85Encode(input, output: TStream): integer并期望通过一个流。接下来,我编写了一个重载函数。
function Z85Encode(b: TBytes): string;它将字节序列写入TBytesStream (与调用encode函数相同),然后将编码数据读入结果字符串。
问题是我发现TStream.Read的行为与文档非常不同,我无法理解它。你我可以用其他方式完成这个函数,但我不太明白为什么?我想知道德尔菲是如何实现TBytes类型的。
为了说明我的问题,我编写了以下测试过程:
procedure Test;
var
iStream: TMemoryStream;
n: integer;
a: TBytes;
b: TBytes
c: array [0..4] of Byte;
begin
b := TEncoding.UTF8.GetBytes('abcdefghij'); // byte from 97 to 106
iStream := TMemoryStream.Create;
try
iStream.Write(b, Length(b));
iStream.Seek(0, soBeginning);
n := iStream.Read(a, 5); // expect only 5 bytes read, but the whole array is back.
ShowMessage(IntToStr(n)); // n is 5
ShowMessage(IntToStr(Length(a))); // length is 10!!
iStream.Seek(0, soBeginning);
n := iStream.Read(c, 5); // c contains random number, not 97, 98, ...
ShowMessage(IntToStr(n)); // n is 5
finally
iStream.Free;
end;
end;第一个问题,根据文档,读应该只读字节数。但是,如果传入一个TBytes变量,它读取整个字节数组,但返回读计数为5。我还想知道为什么我不需要首先为变量a分配内存。看起来,Stream.Read将为变量分配内存,这不是预期的。
第二个问题,什么时候TStream.Read(c, 5),c是array [0..4] of byte。c数组中的值是一些随机值,而不是97、98、99、100和101。
通过进一步测试,如果我将TStream.Write更改为
for n := 0 to High(b) do begin
iStream.Write(b[n], 1);
end;然后Read(a, 5)将不会得到任何结果,Length(a)将得到访问冲突,而Read(c, 5)将得到正确的结果。
、Read、和写似乎都采用了一个开放类型的参数,并根据参数类型的不同表现出不同的行为。如果最终是读取或写入变量的字节值,则行为不同是可以理解的,但它似乎比从变量中确定字节内容要做得更多。然后,、Read、和写将使用相同的变量类型,而不是我所期望的。
发布于 2018-04-17 07:08:00
您不是在编写数组的内容。您正在写入数组的地址。动态数组是一个指针。指针的值就是你正在写的东西。
若要写入数组,必须执行以下操作
iStream.Write(b[0], Length(b));或
iStream.Write(Pointer(b)^, Length(b));我更喜欢后者,因为即使启用了范围检查,它也适用于长度为0的数组。
同样地,从数组中读取。请注意,首先分配读缓冲区是您的责任。那不是你干的。
SetLength(a, 5);
iStream.Read(Pointer(a)^, Length(a));最后,可能最好使用WriteBuffer和ReadBuffer,因为它们结束了错误检查,检查请求的字节数是否实际传输。
https://stackoverflow.com/questions/49871382
复制相似问题