FILESTREAM字节未正确编写

发布于 2025-02-03 16:46:45 字数 388 浏览 2 评论 0原文

为什么使用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

Why do I get the wrong output using the following code in 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;

Got Output : 01 00 02 00 03 00

Expected output : 01 02 03 04 05 06

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

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

发布评论

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

评论(1

岁月静好 2025-02-10 16:46:46

在Delphi 2009+中,String是16位,UTF-16编码Unicodestring。您没有考虑到sizeof(char)是2个字节,而不是您期望的1个字节。 长度(String)以字符数量表示,而不是字节数。您的字符串长度为6个字符,但大小为12个字节。您仅将字符串的第一个字节写入文件。而且,由于您的字符串包含下面的ASCII字符#128,因此每个其他字节都是$ 00

使用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;

不过,您真的不应该是首先使用字符串作为二进制数据。例如,使用字节数组,例如:

var
  bytes: TBytes;
  mystream: TFileStream;
begin
  mystream := TFileStream.Create('C:\Data\test.bmp', fmCreate);
  try
    SetLength(bytes, 6);
    bytes[0] := $1;
    ...
    bytes[5] := $6;
    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;

In Delphi 2009+, string is a 16-bit, UTF-16 encoded UnicodeString. You are not taking into account that SizeOf(Char) is 2 bytes, not 1 byte as you are expecting. Length(string) is expressed in number of characters, not in number of bytes. Your string is 6 characters in length, but is 12 bytes in size. You are writing only the 1st 6 bytes of the string to your file. And since your string contains ASCII characters below #128, every other byte will be $00.

Use an 8-bit AnsiString instead, eg:

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;

Or, use TEncoding to convert the Unicode string to an 8-bit byte encoding:

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;

Alternatively:

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;

Though, you really should not be using a string for binary data in the first place. Use a byte array instead, eg:

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

Or better, just use a TBitmap object, since you are writing to a .bmp file, eg:

var
  bmp: TBitmap;
begin
  bmp := TBitmap.Create;
  try
    ...
    bmp.SaveToFile('C:\Data\test.bmp');
  finally
    bmp.Free;
  end;
end;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文