質問

I am loading a binary file into a memorystream, then encoding the data, and returning the result as a string, then writing the result into another memorystream, and saving it to a file, but when it saved the file is much smaller than the original 25kb from 400kb...lol, im pretty sure it's because I've hit the limit of what a string is capable of handling.

it's definately encoding what data it does save in the new file correctly, I decrypted it and compared it to the begining of the original file.

I know this is a very long winded method and probibly has some unnecesary steps, so loading it into bStream would be a very effective resolution. My question is how could I have the data returned to bStream rather than having it returned to a string then writing the string to bStream at that point as I do believe, that it would solve my problem, any other suggestions would also be appreciated. Im using Delphi 6.

Heres My Code:

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;

Thanks.

役に立ちましたか?

解決

Your length calculations are all wrong as has been pointed out in comments.

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

This means that your encoded stream is 1/12th the size of the input stream. But it needs to be larger. You meant:

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

I also do not see the point of using a string here. You can write directly to the stream.

And, it's worth repeating that with base 64 you are encoding and not encrypting.

In my opinion, there is little point writing all this yourself when Delphi ships with a base 64 implementation. The unit is called EncdDecd, or Soap.EncdDecd if you are using namespaces. And the only function you need is

procedure EncodeStream(Input, Output: TStream);

Create two file streams, one for reading, one for writing, and pass them to that function. For example:

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;

Should you need to reverse the process, do so with, you guessed it, DecodeStream.

If performance matters then you may need to use a buffered stream rather than TFileStream. For example: Buffered files (for faster disk access)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top