2013-10-25 48 views
0

好吧,所以我(很好)最近開始玩拉扎魯斯/免費帕斯卡爾,我有點卡住與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; 

誰能幫助我嗎?

回答

0

我從來沒有聽說過關於ObjectBinaryToText(),但看起來像時髦。另外,什麼是EncodeStringBase64()函數?

首先,您不應該將二進制流轉換爲文本進行編碼,而應該直接對二進制數據進行B64編碼。 B64算法旨在處理字節數組。

自Delphi 6以來,有EncdDecd.pas單元,它實現了B64編碼方法。我不知道,如果拉撒路/ 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; 
+2

[ObjectBinaryToText(http://docwiki.embarcadero.com/Libraries/XE5/en/System.Classes.ObjectBinaryToText)是在Delphi系統單元標準功能,用於讀取dfm資源並將其轉換爲文本。例如,它在IDE中被大量使用。還有逆ObjectTextToBinary,該文本對象轉換成它的二進制版本(使用時DFM資源,您的應用程序被加載在運行時創建實際的窗體和控件)。 –

+0

對於Lazarus/fpc單元base64。包含兩個流和輔助功能編碼/ decidestringbase64() –

+0

我覺得馬可說,我使用的拉撒路它有它自己的base64類,似乎有點挑剔比它的變形怪 –

2

你得到「非法流圖像」異常,因爲您正在加載的文件可能不是二進制DFM文件。這就是ObjectBinaryToText是要處理的。這不是任意數據。所以擺脫那個命令。您也可以跳過TMemoryStreamTStringStream已經有一個LoadFromFile方法,所以你可以直接調用它,而不是涉及另一個緩衝區。

StrStream.LoadFromFile(filename); 

但字符串是不是真的正確的數據結構爲base64編碼它之前保存文件英寸base64編碼的輸入是二進制數據; 輸出是文字。使用文本數據結構作爲中間格式意味着您可能會向數據中引入錯誤,因爲難以將某些數據編碼爲有效字符。您的編碼功能的右側接口是這樣的:

function Base64Encode(Data: TStream): string; 

你不需要將整個文件加載到編碼它之前的記憶。只需打開文件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; 
+0

非常感謝您抽出寶貴時間來幫助,我不敢說,我只花了幾個小時的語言真的,所以我還在掙扎。 首先,我不知道,如果你宣佈解決了這個功能,餘did't覺得它長得很像,但無論如何,我嘗試和失敗:我沒有用delphi,我使用的拉撒路,所以不認爲Base64Encode()存在。 我EncodeStringBase64試了一下()和曾在我拋出的各種錯誤,主要是它似乎想爲AnsiString類型,而不是T流過流,我不知道如何解決這個問題,什麼我試圖似乎讓我更深在泥裏。 –

+0

既然你說你的目標是寫一個base64編碼器,我以爲你會寫的實際編碼功能。我參考的'Base64Encode'函數是你寫的。歡迎您隨時隨地使用您想要的任何東西。你顯然已經明確期望收到一個字符串的功能,並且看臺不是字符串。我解釋了爲什麼我認爲你不應該使用字符串,但是我的答案的上半部分解釋瞭如果你堅持要做什麼。 –