如何剪切 TStringStream 的最后 N 个字符?

How to cut the last N chars of a TStringStream?

我正在将一些字符串写入 TStringStream,使用字符串分隔符将它们分开。

var
  Stream : TStringStream;
  i : integer;
  Separator : string;
begin
  Separator := '|';
  Stream := TStringStream.Create('');
  try
    i := 0;
    while(i < 5) do
    begin
      Stream.WriteString(IntToStr(i) + ' test' + Separator);
      Inc(i);
    end;

    Stream.Size := Stream.Size - Length(Separator) * SizeOf(Char);

    Stream.SaveToFile('.\test.txt');
  finally
    Stream.Free;
  end;
end;

在循环结束时,我想删除最后一个分隔符:

Stream.Size := Stream.Size - Length(Separator) * SizeOf(Char);

它产生以下 test.txt 输出文件:

0 test|1 test|2 test|3 test|4 tes

SizeOf(Char) in Delphi XE7 是 2,但似乎 TStringString 每个字符使用一个字节。我不认为我可以假设它总是 1 个字节,那么我怎样才能安全地从流中删除最后 N 个字符?

可以使用TEncoding.GetByteCount方法完成。

Returns the number of bytes generated by encoding Chars. Note that the number of bytes in a string is not necessarily exactly proportional to the number of characters in a given character array or string.

The Chars parameter can be a character array or a character pointer containing the bytes to be counted.

The S parameter refers to a UnicodeString from which the Byte count will be extracted.

The CharCount parameter specifies the number of characters to encode.

The CharIndex parameter indicates the index within the Chars array where counting should begin.

The CharCount parameter indicates the number of characters that should be included when counting the bytes.

The Return Value is the number of bytes in the passed Chars or S parameter.

可以按如下方式从字符串流中删除最后一个分隔符:

Stream.Size := Stream.Size - Stream.Encoding.GetByteCount(Separator);

TStringStream 的大小 属性 在写入数据时会自动(并且不可避免地)更新。所以肯定要做的事情是单独编写分隔符并立即记录流的大小 before 你做到了吗?然后,当您想要丢弃最后一个分隔符时,您可以轻松地在该点截断流。

var
  PrvSize : Int64;;

[...]
  PrvSize := Stream.Size
  Stream.WriteString(Separator);
[...]
  Stream.Size := PrvSize;