意外的行为重复使用Delphi中的Tmemorystream

发布于 2025-01-21 08:57:39 字数 770 浏览 0 评论 0 原文

我正在尝试从Tmemorystream读取两条不同长度的字符串,但是这两个流的长度最终都相同。因此,例如,如果第一个字符串是“ abcdefghijkl',而第二个字符串是“ wxyz”,那么我对第二个字符串获得的值是'wxyzefghijkl'(我的新字符串的前四个字符('wxyz')遵循通过“ WXYZ”替换的第一字符串的剩余字符

是: -

var
  L : LongInt
  S : string;

...
  msRecInfo.Position := 0;
  msRecInfo.Read(L, SizeOf(L)); // read size of following string ...

  SubStream.Clear;
  SubStream.CopyFrom(msRecInfo, L); // copy next block of data to a second TMemoryStream

  if (L > 0) then S := StreamToString(SubStream);  //convert the stream into a string

  msRecInfo.Read(L, SizeOf(L)); // get size of following string ...
  SubStream.CopyFrom(msRecInfo, L);
  if (L > 0) then S := StreamToString(SubStream);

我一直在与这个数小时的战斗而没有成功。

I am trying to read two strings of varying length from a TMemoryStream, but both streams end up being the same length. So if, for example, the first string is 'abcdefghijkl', and the second one is 'wxyz', the value I get for the second string is 'wxyzefghijkl' (the first four characters of my new string ('wxyz') followed by the remaining characters of the 1st string that have not been replaced by 'wxyz'

My code is:-

var
  L : LongInt
  S : string;

...
  msRecInfo.Position := 0;
  msRecInfo.Read(L, SizeOf(L)); // read size of following string ...

  SubStream.Clear;
  SubStream.CopyFrom(msRecInfo, L); // copy next block of data to a second TMemoryStream

  if (L > 0) then S := StreamToString(SubStream);  //convert the stream into a string

  msRecInfo.Read(L, SizeOf(L)); // get size of following string ...
  SubStream.CopyFrom(msRecInfo, L);
  if (L > 0) then S := StreamToString(SubStream);

I have been battling with this for hours without success. Can anyone point out what I am doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

简单气质女生网名 2025-01-28 08:57:39

在第二个调用 substream.copyfrom()之前,您没有调用 substream.clear()。因此,第一个调用 streamToString(substream) subs substream.position.position 在流的末尾,然后是后续 substream.copyfrom()将更多数据添加到流中,保存现有数据。然后,随后的 streamTostring(substream) substream 中读取所有数据。

另外,请注意,如果 l 0 将其传递给 substream.copyfrom()时,它将复制整个 thother /em> msrecinfo 流。这是记录的行为:

如果计数为0,则copyfrom将源位置设置为0,然后在阅读之前将源位置设置为0,然后将整个源内容的整个内容复制到流中。如果计数大于或小于0源位置。

因此,您需要向上移动 l> 0 检查,例如:

msRecInfo.Read(L, SizeOf(L));
if (L > 0) then
begin
  SubStream.Clear;
  SubStream.CopyFrom(msRecInfo, L);
  S := StreamToString(SubStream);
end
else
  S := '';

我建议将此逻辑包装到可重复使用的函数中,例如:

var
  L : LongInt;
  S : string;

  function ReadString: string;
  begin
    msRecInfo.Read(L, SizeOf(L)); // read size of following string ...
    if (L > 0) then
    begin
      SubStream.Clear;
      SubStream.CopyFrom(msRecInfo, L); // copy next block of data to a second TMemoryStream
      Result := StreamToString(SubStream);  //convert the stream into a string
    end else
      Result := '';
  end;
begin
  ...
  msRecInfo.Position := 0;
  S := ReadString;
  S := ReadString;
  ...

虽然,如果可行的话,我建议只能摆脱 substream 完全,更新 streamtostring( ) l 作为输入参数,因此您可以直接从 MSRECINFO 直接读取 String ,例如:

msRecInfo.Read(L, SizeOf(L));
S := StreamToString(msRecInfo, L);

无需2nd tmemorystream 如果可以避免。

You are not calling SubStream.Clear() before the 2nd call to SubStream.CopyFrom(). So, the 1st call to StreamToString(SubStream) leaves SubStream.Position at the end of the stream, then the subsequent SubStream.CopyFrom() adds more data to the stream, preserving the existing data. Then the subsequent StreamToString(SubStream) reads all of the data from SubStream.

Also, be aware that if L is 0 when you pass it to SubStream.CopyFrom(), it will copy the entire msRecInfo stream. This is documented behavior:

https://docwiki.embarcadero.com/Libraries/en/System.Classes.TStream.CopyFrom

If Count is 0, CopyFrom sets Source position to 0 before reading and then copies the entire contents of Source into the stream. If Count is greater than or less than 0, CopyFrom reads from the current position in Source.

So, you need to move up your L > 0 check, eg:

msRecInfo.Read(L, SizeOf(L));
if (L > 0) then
begin
  SubStream.Clear;
  SubStream.CopyFrom(msRecInfo, L);
  S := StreamToString(SubStream);
end
else
  S := '';

I would suggest wrapping this logic into a reusable function, eg:

var
  L : LongInt;
  S : string;

  function ReadString: string;
  begin
    msRecInfo.Read(L, SizeOf(L)); // read size of following string ...
    if (L > 0) then
    begin
      SubStream.Clear;
      SubStream.CopyFrom(msRecInfo, L); // copy next block of data to a second TMemoryStream
      Result := StreamToString(SubStream);  //convert the stream into a string
    end else
      Result := '';
  end;
begin
  ...
  msRecInfo.Position := 0;
  S := ReadString;
  S := ReadString;
  ...

Although, if feasible, I would suggest just getting rid of SubStream altogether, update StreamToString() to take L as an input parameter, so that you can read the string from msRecInfo directly, eg:

msRecInfo.Read(L, SizeOf(L));
S := StreamToString(msRecInfo, L);

No need for a 2nd TMemoryStream if you can avoid it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文