uses
Classes, Contnrs;
type
TVocabulary =
class
Language1:
string;
Language2:
string;
Note:
string;
AddedOn: TDateTime;
LastTraining: TDateTime;
Chance: Single;
Mistakes: Integer;
Trials: Integer;
Box: Integer;
protected
procedure WriteToStream(AStream: TStream);
procedure ReadFromStream(AStream: TStream);
end;
TVocabularyList =
class(TObjectList)
LanguageName1:
string;
LanguageName2:
string;
Note:
string;
public
procedure WriteToStream(AStream: TStream);
procedure ReadFromStream(AStream: TStream);
end;
procedure SaveToFile(AList: TVocabularyList; AFilename:
string);
procedure LoadFromFile(AList: TVocabularyList; AFilename:
string);
implementation
uses
SysUtils, Windows,
ZLib;
type
TFileHeader =
record
Ident:
array[1..10]
of Char;
procedure WriteToStream(AStream: TStream);
procedure ReadFromStream(AStream: TStream);
class operator Explicit(v: TFileHeader):
string;
end;
TRecordHeader =
record
Ident:
string;
Version: LongWord;
procedure WriteToStream(AStream: TStream);
procedure ReadFromStream(AStream: TStream);
end;
const
VocabularyIdent_File: TFileHeader = (Ident: ('
V','
o','
c','
a','
b','
u','
l','
a','
r','
y'));
VocabularyIdent_Header: TRecordHeader = (Ident: '
Header'; Version: $00010000);
VocabularyIdent_Items: TRecordHeader = (Ident: '
Items'; Version: $00010000);
procedure WriteStringToStream(AStream: TStream;
const AValue:
string);
var
c: LongWord;
begin
c := Length(AValue);
AStream.WriteBuffer(c, SizeOf(c));
AStream.WriteBuffer(PChar(AValue)^, c);
end;
procedure ReadStringFromStream(AStream: TStream;
var AValue:
string);
var
c: LongWord;
begin
AStream.ReadBuffer(c, SizeOf(c));
SetLength(AValue, c);
AStream.ReadBuffer(PChar(AValue)^, c);
end;
procedure TFileHeader.WriteToStream(AStream: TStream);
begin
AStream.WriteBuffer(Ident, SizeOf(Ident));
end;
class operator TFileHeader.Explicit(v: TFileHeader):
string;
var
i: Integer;
begin
Result := '
';
for i := Low(v.Ident)
to High(v.Ident)
do
begin
if v.Ident[i] = #0
then
Exit;
Result := Result + v.Ident[i];
end;
end;
procedure TFileHeader.ReadFromStream(AStream: TStream);
begin
AStream.ReadBuffer(Ident, SizeOf(Ident));
end;
procedure TRecordHeader.WriteToStream(AStream: TStream);
begin
WriteStringToStream(AStream, Ident);
AStream.WriteBuffer(Version, SizeOf(Version));
end;
procedure TRecordHeader.ReadFromStream(AStream: TStream);
begin
ReadStringFromStream(AStream, Ident);
AStream.ReadBuffer(Version, SizeOf(Version));
end;
procedure TVocabularyList.WriteToStream(AStream: TStream);
var
i, c: LongWord;
begin
{Datei-Inhalt}
VocabularyIdent_File.WriteToStream(AStream);
{Header}
VocabularyIdent_Header.WriteToStream(AStream);
WriteStringToStream(AStream, LanguageName1);
WriteStringToStream(AStream, LanguageName2);
WriteStringToStream(AStream, Note);
{Items}
VocabularyIdent_Items.WriteToStream(AStream);
c := Count;
AStream.WriteBuffer(c, SizeOf(c));
for i := 0
to c - 1
do
TVocabulary(Items[i]).WriteToStream(AStream);
end;
procedure TVocabularyList.ReadFromStream(AStream: TStream);
{---}
procedure CheckRecordHeader(
const AValue, AReferenz: TRecordHeader);
begin
if AValue.Ident <> AReferenz.Ident
then
raise Exception.CreateFmt('
ungültiges Dateiformat, ''
%s''
erwartet',
[AReferenz.Ident]);
end;
{---}
procedure CheckRecordVersion(
const AValue, AReferenz: TRecordHeader);
begin
if AValue.Ident <> AReferenz.Ident
then
raise Exception.CreateFmt('
ungültige Recordversion ''
%s''
V%d.%d',
[AValue.Ident, HiWord(AValue.Version), LoWord(AValue.Version)]);
end;
{---}
var
i, c: LongWord;
FileHeader: TFileHeader;
RecordHeader: TRecordHeader;
v: TVocabulary;
begin
LanguageName1 := '
';
LanguageName2 := '
';
Note := '
';
Clear;
{Datei-Inhalt}
FileHeader.ReadFromStream(AStream);
if FileHeader.Ident <> VocabularyIdent_File.Ident
then
raise Exception.CreateFmt('
ungültiges Dateiformat, %s erwartet',
[
string(VocabularyIdent_File)]);
{Header}
RecordHeader.ReadFromStream(AStream);
CheckRecordHeader(RecordHeader, VocabularyIdent_Header);
CheckRecordVersion(RecordHeader, VocabularyIdent_Header);
ReadStringFromStream(AStream, LanguageName1);
ReadStringFromStream(AStream, LanguageName2);
ReadStringFromStream(AStream, Note);
{Items}
RecordHeader.ReadFromStream(AStream);
CheckRecordHeader(RecordHeader, VocabularyIdent_Items);
CheckRecordVersion(RecordHeader, VocabularyIdent_Items);
AStream.ReadBuffer(c, SizeOf(c));
for i := 0
to c - 1
do
begin
v := TVocabulary.Create;
try
v.ReadFromStream(AStream);
except
v.Free;
raise;
end;
Add(v);
end;
end;
procedure TVocabulary.WriteToStream(AStream: TStream);
begin
WriteStringToStream(AStream, Language1);
WriteStringToStream(AStream, Language2);
WriteStringToStream(AStream, Note);
AStream.WriteBuffer(AddedOn, SizeOf(AddedOn));
AStream.WriteBuffer(LastTraining, SizeOf(LastTraining));
AStream.WriteBuffer(Chance, SizeOf(Chance));
AStream.WriteBuffer(Mistakes, SizeOf(Mistakes));
AStream.WriteBuffer(Trials, SizeOf(Trials));
AStream.WriteBuffer(Box, SizeOf(Box));
end;
procedure TVocabulary.ReadFromStream(AStream: TStream);
begin
ReadStringFromStream(AStream, Language1);
ReadStringFromStream(AStream, Language2);
ReadStringFromStream(AStream, Note);
AStream.ReadBuffer(AddedOn, SizeOf(AddedOn));
AStream.ReadBuffer(LastTraining, SizeOf(LastTraining));
AStream.ReadBuffer(Chance, SizeOf(Chance));
AStream.ReadBuffer(Mistakes, SizeOf(Mistakes));
AStream.ReadBuffer(Trials, SizeOf(Trials));
AStream.ReadBuffer(Box, SizeOf(Box));
end;
procedure SaveToFile(AList: TVocabularyList; AFilename:
string);
var
stream: TStream;
begin
stream := TFileStream.Create(AFilename, fmCreate);
try
stream := TCompressionStream.Create(clDefault, stream);
AList.WriteToStream(stream);
finally
stream.Free;
end;
end;
procedure LoadFromFile(AList: TVocabularyList; AFilename:
string);
var
stream: TStream;
begin
stream := TFileStream.Create(AFilename, fmOpenRead, fmShareDenyWrite);
try
stream := TDecompressionStream.Create(stream);
AList.ReadFromStream(stream);
finally
stream.Free;
end;
end;