0

我正在将二进制文件加载到内存流中,然后对数据进行编码,并将结果作为字符串返回,然后将结果写入另一个内存流,并将其保存到文件中,但是保存时文件比原始文件小得多从 400kb 到 25kb...大声笑,我很确定这是因为我已经达到了字符串能够处理的极限。

它肯定会正确编码它确实保存在新文件中的数据,我将其解密并将其与原始文件的开头进行比较。

我知道这是一个非常冗长的方法,并且可能有一些不必要的步骤,因此将其加载到 bStream 将是一个非常有效的解决方案。我的问题是如何将数据返回到 bStream 而不是将其返回到字符串然后将字符串写入 bStream ,因为我相信它会解决我的问题,任何其他建议也将不胜感激。我正在使用德尔福 6。

这是我的代码:

function B64Encode(pInput: pointer; pOutput: pointer; Size: longint): longint;
var
  i, iptr, optr: integer;
  Input, Output: PByteArray;
begin
  Input := PByteArray(pInput);
  Output := PByteArray(pOutput);
  iptr := 0;
  optr := 0;
  for i := 1 to (Size div 3) do
  begin
    Output^[optr + 0] := B64[Input^[iptr] shr 2];
    Output^[optr + 1] := B64[((Input^[iptr] and 3) shl 4) + (Input^[iptr + 1] shr 4)];
    Output^[optr + 2] := B64[((Input^[iptr + 1] and 15) shl 2) + (Input^[iptr + 2] shr 6)];
    Output^[optr + 3] := B64[Input^[iptr + 2] and 63];
    Inc(optr, 4);
    Inc(iptr, 3);
  end;
  case (Size mod 3) of
    1:
      begin
        Output^[optr + 0] := B64[Input^[iptr] shr 2];
        Output^[optr + 1] := B64[(Input^[iptr] and 3) shl 4];
        Output^[optr + 2] := byte('=');
        Output^[optr + 3] := byte('=');
      end;
    2:
      begin
        Output^[optr + 0] := B64[Input^[iptr] shr 2];
        Output^[optr + 1] := B64[((Input^[iptr] and 3) shl 4) + (Input^[iptr + 1] shr 4)];
        Output^[optr + 2] := B64[(Input^[iptr + 1] and 15) shl 2];
        Output^[optr + 3] := byte('=');
      end;
  end;
  Result := ((Size + 2) div 3) * 4;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  aStream, bStream: TMemoryStream;
  strastream: string;
  szaStream: integer;
begin
  bStream := TMemoryStream.Create;
  aStream := TMemoryStream.Create;
  aStream.LoadFromFile('C:\file1.exe'); 
  szaStream := (astream.size + 2) div (3 * 4);
  SetLength(strastream, szaStream);
  B64Encode(astream.Memory, @strastream[1], Length(strastream));
  bstream.WriteBuffer(strastream[1], szaStream);
  AttachToFile('C:\file2.exe', bStream); 
  bstream.Free;
  aStream.Free;    
end;

谢谢。

4

1 回答 1

6

正如评论中指出的那样,您的长度计算都是错误的。

szaStream := (astream.size + 2) div (3 * 4);

这意味着您的编码流是输入流大小的 1/12。但它需要更大。你的意思是:

szaStream := ((astream.size * 4) div 3) + 2;

我也没有看到在这里使用字符串的意义。您可以直接写入流。

而且,值得重复的是,使用 base 64 是在编码而不是加密。

在我看来,当 Delphi 提供 base 64 实现时,自己编写所有这些内容没有什么意义。该单元称为 EncdDecd,如果您使用命名空间,则称为 Soap.EncdDecd。你需要的唯一功能是

procedure EncodeStream(Input, Output: TStream);

创建两个文件流,一个用于读取,一个用于写入,并将它们传递给该函数。例如:

procedure EncodeFileBase64(const InFileName, OutFileName:string);
var
  Input, Output: TStream;
begin
  Input := TFileStream.Create(InFileName, fmOpenRead);
  try
    Output := TFileStream.Create(InFileName, fmCreate);
    try
      EncodeStream(Input, Output);
    finally
      Output.Free;
    end;
  finally
    Input.Free;
  end;
end;

如果您需要反转该过程,请使用您猜对的 DecodeStream。

如果性能很重要,那么您可能需要使用缓冲流而不是 TFileStream。例如:缓冲文件(用于更快的磁盘访问)

于 2013-08-15T05:27:33.583 回答