文件流字节未正确写入

Filestream Bytes not written properly

为什么在 RAD Studio 10.1 中使用以下代码会得到错误的输出?

var
  sPalette : string;
  mystream: TfileStream;
begin
  mystream := TfileStream.Create('C:\Data\test.bmp', fmCreate);
  sPalette := #1#2#3#4#5#6;
  mystream.WriteBuffer(Pointer(sPalette)^, Length(sPalette));
  mystream.Free;
end;

得到输出:01 00 02 00 03 00

预期输出:01 02 03 04 05 06

在 Delphi 2009+ 中,string 是一个 16 位、UTF-16 编码的 UnicodeString。您没有考虑到 SizeOf(Char) 是 2 个字节,而不是您期望的 1 个字节。 Length(string)是用字符数表示的,不是字节数。您的字符串长度为 6 个字符,但大小为 12 个字节。您只将 string 的前 6 个字节写入您的文件。由于您的 string 包含 #128 以下的 ASCII 字符,每隔一个字节将是 [=22=].

改用 8 位 AnsiString,例如:

var
  sPalette : AnsiString;
  mystream: TFileStream;
begin
  mystream := TFileStream.Create('C:\Data\test.bmp', fmCreate);
  try
    sPalette := #1#2#3#4#5#6;
    mystream.WriteBuffer(Pointer(sPalette)^, Length(sPalette));
  finally
    mystream.Free;
  end;
end;

或者,使用TEncoding将Unicode字符串转换为8位字节编码:

var
  sPalette : string;
  bytes: TBytes;
  mystream: TFileStream;
begin
  mystream := TFileStream.Create('C:\Data\test.bmp', fmCreate);
  try
    sPalette := #1#2#3#4#5#6;
    bytes := TEncoding.Default.GetBytes(sPalette);
    mystream.WriteBuffer(Pointer(bytes)^, Length(bytes));
  finally
    mystream.Free;
  end;
end;

或者:

var
  sPalette : string;
  mystream: TStreamWriter;
begin
  mystream := TStreamWriter.Create('C:\Data\test.bmp', False, TEncoding.Default);
  try
    sPalette := #1#2#3#4#5#6;
    mystream.Write(sPalette);
  finally
    mystream.Free;
  end;
end;

不过,您真的不应该首先对二进制数据使用 string。请改用字节数组,例如:

var
  bytes: TBytes;
  mystream: TFileStream;
begin
  mystream := TFileStream.Create('C:\Data\test.bmp', fmCreate);
  try
    SetLength(bytes, 6);
    bytes[0] := ;
    ...
    bytes[5] := ;
    mystream.WriteBuffer(Pointer(bytes)^, Length(bytes));
  finally
    mystream.Free;
  end;
end;

或者更好,只使用 TBitmap 对象,因为您正在写入 .bmp 文件,例如:

var
  bmp: TBitmap;
begin
  bmp := TBitmap.Create;
  try
    ...
    bmp.SaveToFile('C:\Data\test.bmp');
  finally
    bmp.Free;
  end;
end;