TIniFile.WriteBinaryStream создает исключение - PullRequest
1 голос
/ 02 августа 2020

В 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;

1 Ответ

1 голос
/ 02 августа 2020

Я считаю, что это ограничение функций операционной системы для обработки файлов INI; строка слишком длинная для этого.

Если вместо этого вы используете реализацию Delphi INI-файла, TMemIniFile, она работает нормально. Только не забудьте в конце вызвать MyIni.UpdateFile.

Да, это действительно ограничение в 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;

(Напомним, что файлы INI изначально использовались для хранения небольших объемов данных конфигурации в 16-битной Windows эпохе.)

Также , Уве Раабе прав: вы должны сохранить строку Base64 как текст.

...