2013-08-15 2 views
0

Я загружаю двоичный файл в memystream, затем кодирую данные и возвращаю результат в виде строки, затем записывая результат в другой memystream и сохраняя его в файл, но при его сохранении файл намного меньше, чем оригинальный 25kb от 400kb ... lol, im уверен, что это потому, что я попал в предел того, что строка может обрабатывать.Зашифрованный файл Delphi намного меньше оригинала?

он определенно кодирует, какие данные он сохраняет в новом файле правильно, я расшифровал его и сравнил с началом исходного файла.

Я знаю, что это очень длинный метод и, возможно, имеет некоторые ненужные шаги, поэтому загрузка его в bStream будет очень эффективным разрешением. Мой вопрос в том, как я мог вернуть данные в bStream, а не возвращать его в строку, а затем записывать строку в bStream в этот момент, как я полагаю, что это решит мою проблему, и любые другие предложения также будут оценены. Им с помощью Delphi 6.

Heres мой код:

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

FYI, Base64 - это кодировка, а не шифрование. – Blorgbeard

+0

'szaStream: = (astream.size + 2) div (3 * 4);' наверняка проблема? вы по какой-то причине делят на 12? – Blorgbeard

+1

Я подозреваю, что они хотели умножить на 4/3, но добавили скобки в неправильном месте. –

ответ

6

Ваши расчеты длины ошибочны, как указано в комментариях.

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

Это означает, что ваш кодированный поток равен 1/12 размера входного потока. Но он должен быть больше. Вы имели в виду:

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

Я также не вижу смысла использовать строку здесь. Вы можете напрямую писать в поток.

И стоит повторить, что с базой 64 вы кодируете и не шифруете.

На мой взгляд, есть немного смысла писать все это самостоятельно, когда Delphi поставляется с базой 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. Например: Buffered files (for faster disk access)

+0

Просто FYI, функции кодирования в 'Soap.EncdDecd' вставляют строку разрыва каждые 75 символов в кодированном выходе. Для сравнения, класс 'TIdEncoderMIME' в Indy, который поставляется с Delphi, не вставляет никаких разрывов строки в свой вывод base64. И он поддерживает кодирование/декодирование данных String, Bytes и TStream. –

Смежные вопросы