一個設計優良的試題庫系統,除了支持文本數據以外,還應該支持公式、圖片、表格等非文本數據,這樣才能很好地支持已有的試題形式。筆者前一陣子使用過一個“XXX考核題庫系統”,該軟件使用Paradox作為數據庫,只能支持文本題目,無法滿足現實試題的要求,為此對其進行了更改。
對於非文本數據的支持可以采用OLE嵌入Word文檔的方法,但這種技術實現起來比較復雜,本文給出一種簡單而實用的方法:非文本數據用rtf文檔導入到存儲,編輯器采用RichTextBox。RichTextBox是微軟提供的一個ActiveX,導入到Delphi中之後,使用起來就同其他組件一樣方便。RichTextBox可以很好地支持文本、公式、圖片、表格等,而且它有一個TextRTF屬性可供訪問,可以把這些文檔元素自動轉為rtf字符串。比如把RichTextBox1的內容賦給RichTextBox2時,只需要RichTextBox2.TextRTF := RichTextBox1.TextRTF就可以了。
另外非文本數據往往數據量比較大,因此可以在輸入到數據庫時可以進行數據壓縮,而在導出時進行還原,從而減少存放數據量,而又不影響使用。
結合這兩點,可以這樣實現非文本數據的處理:試題內容用Word或者寫字板編輯後加載到RichTextBox中,在RichTextBox中可以進行必要的編輯。存儲到數據庫時先得到RichTextBox的TextRTF字符串,經過壓縮後存儲到數據庫。而生成試卷時從數據庫中讀出字符串,然後解壓得到原來的TextRTF字符串,加載到RichTextBox中,而後就可以用來進一步的處理得到圖文並茂的試卷。
壓縮時可以使用zlib來壓縮(要引用zlib單元),然後使用下面兩個函數。
壓縮函數
function MyCompress(str: string): string;
var
nSize: integer; // ***此處必須與DeCompress中的類型一致
strmCompression: TCompressionStream;
strmMemory1, strmMemory2: TMemoryStream;
begin
nSize := Length(str);
strmMemory1 := TMemoryStream.Create;
try
strmCompression := TCompressionStream.Create(cldefault, strmMemory1);
try
strmCompression.Write(str[1], nSize);
finally
FreeAndNil(strmCompression);
end;
strmMemory1.Position := 0;
strmMemory2 := TMemoryStream.Create;
try
strmMemory2.WriteBuffer(nSize, sizeof(nSize));
strmMemory1.SaveToStream(strmMemory2);
strmMemory2.Position := 0;
SetLength(result, strmMemory2.Size);
strmMemory2.Read(result[1], strmMemory2.Size);
finally
FreeAndNil(strmMemory2);
end;
finally
FreeAndNil(strmMemory1);
end;
end;
解壓縮函數
function MyDecompress(str: string): string;
var
nSize: integer;
strmDecompression: TDecompressionStream;
strmMemory: TMemoryStream;
begin
strmMemory := TMemoryStream.Create;
try
strmMemory.Write(str[1], Length(str));
strmMemory.Position := 0;
strmMemory.ReadBuffer(nSize, sizeof(nSize));
strmDecompression := TDecompressionStream.Create(strmMemory);
try
SetLength(result, nSize);
strmDecompression.ReadBuffer(result[1], nSize);
finally
FreeAndNil(strmDecompression);
end;
finally
FreeAndNil(strmMemory);
end;
end;
經過測試發現,大多數的RTF文檔都可以得到很好的壓縮率:即使是全部是文本信息的RTF文檔也可以得到倍左右的壓縮率,而如果是以圖像為主的RTF可以得到10倍甚至高達幾十倍的壓縮率。
下面是測試壓縮、解壓縮、壓縮率的代碼:
procedure TForm1.Test;
var
i, j: integer;
begin
RichTextBox2.TextRTF := MyDecompress(MyCompress(RichTextBox1.TextRTF));
i := Length(RichTextBox1.TextRTF);
j := Length(MyCompress(RichTextBox1.TextRTF));
ShowMessage('Length Before Compression: ' + IntToStr(i)
+ '; Length After Compression: ' + IntToStr(j)
+ '; Compression Ratio: ' + IntToStr(Round(i/j)));
end;
(函數測試環境:Windows 2000 Profressional + Delphi 6)