0

好的,所以我(非常)最近开始玩 lazaruz/free pascal,我有点坚持使用 TMemoryStream 和它的流媒体来阅读文件。

我正在尝试编写一个简单的 base64 编码器,它可以编码文本字符串或文件(如图像和 WAV),然后在 html 和 javascript 中使用。

以下代码编译得很好,但我EReadError Illegal stream image在尝试加载文件时得到了。我将包含仅工作字符串的过程以供参考:

procedure TForm1.TextStringChange(Sender: TObject);
    begin
    Memo1.Lines.Text := EncodeStringBase64(TextString.Text);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
   Memo1.Lines.Text := '';
   Form1.BorderIcons :=  [biSystemMenu,biMinimize];
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
    if OpenDialog1.Execute then
    begin
     filename := OpenDialog1.Filename;
     stream := TMemoryStream.Create;
       try
         StrStream := TStringStream.Create(s);
           try
              stream.LoadFromFile(filename);
              stream.Seek(0, soFromBeginning);
              ObjectBinaryToText(stream, StrStream);
              StrStream.Seek(0, soFromBeginning);
              Memo1.Lines.Text := EncodeStringBase64(StrStream.DataString);
           finally
              StrStream.Free;
           end;
       finally
           stream.Free;
       end;
    end;
end;   

谁能帮我吗?

4

2 回答 2

2

您会收到“非法流图像”异常,因为您正在加载的文件可能不是二进制 DFM 文件。这ObjectBinaryToText就是要处理的内容。它不适用于任意数据。所以摆脱那个命令。

您也可以跳过TMemoryStreamTStringStream已经有一个LoadFromFile方法,所以你可以直接调用它而不是涉及另一个缓冲区。

StrStream.LoadFromFile(filename);

但是,在对文件进行 base64 编码之前,字符串并不是真正适合存储文件的数据结构。base64 编码的输入是二进制数据;输出是文本。使用文本数据结构作为中间格式意味着您可能会因为难以将某些数据编码为有效字符而将错误引入数据中。编码功能的正确接口是这样的:

function Base64Encode(Data: TStream): string;

您不需要在编码之前将整个文件加载到内存中。只需使用 a 打开文件并将其TFileStream传递给您的编码函数。使用流的方法一次从其中读取几个字节Read,将它们编码为 base64,并将它们附加到结果字符串中。(如果你发现你需要它们,你可以使用一个中间体TStringBuilder来收集结果,你可以在文件读取周围添加不​​同的缓冲。不过,不要马上担心这些;首先让你的程序正常工作。)

像这样使用它:

procedure TForm1.BitBtn1Click(Sender: TObject);
var
  filename: string;
  stream: TStream;
begin
  if OpenDialog1.Execute then begin
    filename := OpenDialog1.Filename;
    stream := TFileStream.Create(filename, fmOpenRead);
    try
      Memo1.Lines.Text := Base64Encode(stream);
    finally
      stream.Free;
    end;
  end;
end;
于 2013-10-25T16:22:24.507 回答
0

我以前从未听说过ObjectBinaryToText(),但看起来很时髦。还有,什么是EncodeStringBase64()功能?

首先,您不应该将二进制流转换为文本来对其进行编码,而应该直接对二进制数据进行 B64 编码。B64 算法旨在处理字节数组。

从 Delphi 6 开始,就有EncdDecd.pas了实现 B64 编码方式的单元。我不确定 Lazarus/FPC 是否有此功能,但如果有,您的 B64 编码文件代码应如下所示(添加EncdDecd到使用列表):

procedure TForm1.Button1Click(Sender: TObject);
var
  instream : TFileStream;
  outstream: TStringStream;
begin
  if OpenDialog1.Execute then
  begin
    instream := TFileStream.Create(OpenDialog1.FileName, fmOpenRead or fmShareDenyNone);
    try
      outstream := TStringStream.Create;
      try
        EncodeStream(instream, outstream);
        Memo1.Lines.Text := outstream.DataString;
      finally
        outstream.Free;
      end;
    finally
      instream.Free;
    end;
  end;
end;
于 2013-10-25T16:21:22.633 回答