【问题标题】:TIniFile.WriteBinaryStream creates exceptionTIniFile.WriteBinaryStream 创建异常
【发布时间】:2020-11-22 17:27:44
【问题描述】:

在 Delphi 10.4 中,我尝试将有效的 TPicture base64 编码保存到 INI 文件中:

procedure TForm1.SavePictureToIniFile(const APicture: TPicture);
var
  LInput: TMemoryStream;
  LOutput: TMemoryStream;
  MyIni: TIniFile;
  ThisFile: string;
begin
  if FileSaveDialog1.Execute then
    ThisFile := FileSaveDialog1.FileName
  else EXIT;

  LInput := TMemoryStream.Create;
  LOutput := TMemoryStream.Create;
  try
    APicture.SaveToStream(LInput);
    LInput.Position := 0;
    TNetEncoding.Base64.Encode(LInput, LOutput);
    LOutput.Position := 0;

    MyIni := TIniFile.Create(ThisFile);
    try
      MyIni.WriteBinaryStream('Custom', 'IMG', LOutput); // Exception# 234
    finally
      MyIni.Free;
    end;
  finally
    LInput.Free;
    LOutput.Free;
  end;
end;

WriteBinaryStream 创建异常:

ERROR_MORE_DATA 234 (0xEA) 有更多数据可用。

为什么?这是什么意思?这个问题怎么解决?

编辑:考虑到@Uwe Raabe 和@Andreas Rejbrand 所说的,这段代码(不使用base64 编码)现在可以工作了:

procedure TForm1.SavePictureToIniFile(const APicture: TPicture);
var
  LInput: TMemoryStream;
  MyIni: System.IniFiles.TMemIniFile;
  ThisFile: string;
begin
  if FileSaveDialog1.Execute then
    ThisFile := FileSaveDialog1.FileName
  else EXIT;

  LInput := TMemoryStream.Create;
  try
    APicture.SaveToStream(LInput);
    LInput.Position := 0;

    MyIni := TMemIniFile.Create(ThisFile);
    try
      MyIni.WriteBinaryStream('Custom', 'IMG', LInput);
      MyIni.UpdateFile;
    finally
      MyIni.Free;
    end;
  finally
    LInput.Free;
  end;
end;

【问题讨论】:

  • 您应该使用没有 Base64 编码的 WriteBinaryStream 或编码为 Base64 并改用 WriteString。 Base64 已经是一种文本表示。将其作为二进制流会使所需的内存加倍。
  • @UweRaabe:更不用说结果字符串甚至不是图像的 Base64 编码版本
  • (请注意,当前的解决方案实际上并没有使用 Base64。)

标签: delphi stream ini delphi-10.4-sydney


【解决方案1】:

我认为这是操作系统处理 INI 文件功能的限制;字符串太长了。

如果您改用 Delphi INI 文件实现 TMemIniFile,它就可以正常工作。只是不要忘记在最后打电话给MyIni.UpdateFile

是的,这确实是the Windows API 中的一个限制,如以下最小示例所示:

var
  wini: TIniFile;
  dini: TMemIniFile;
begin

  wini := TIniFile.Create('C:\Users\Andreas Rejbrand\Desktop\winini.ini');
  try
    wini.WriteString('General', 'Text', StringOfChar('W', 10*1024*1024));
  finally
    wini.Free;
  end;

  dini := TMemIniFile.Create('C:\Users\Andreas Rejbrand\Desktop\pasini.ini');
  try
    dini.WriteString('General', 'Text', StringOfChar('D', 10*1024*1024));
    dini.UpdateFile;
  finally
    dini.Free;
  end;

(回想一下,在 16 位 Windows 时代,INI 文件最初用于存储少量配置数据。)

另外Uwe Raabe 是对的:您应该将 Base64 字符串保存为文本。

【讨论】:

  • 顺便说一句:难道没有一种 BinaryStream 可以自动压缩其数据吗?那将非常有用!
  • @user1580348:也许你可以使用TZipFile 来做这个?
  • 我应该使用来自System.ZLib 还是来自ZLibExTZCompressionStream?哪个更好?
  • @user1580348:不知道!
  • 我创建了一个新问题,因为使用 ZLib 压缩流似乎不适用于我的实现:stackoverflow.com/questions/63217195/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-06
  • 2020-04-16
相关资源
最近更新 更多