Einzelnen Beitrag anzeigen

Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.464 Beiträge
 
Delphi 12 Athens
 
#21

Re: Speichern eines großen Arrays

  Alt 6. Apr 2010, 15:26
Zitat von Shubit:
Nun ich bin für alle Lösungen offen, aber da Datenbanken extra für großen Mengen an Daten ausgelegt sind, sollten sie gerade für längere Vokabellisten sehr gut geeignet sein und wenn sie die restlichen Anforderungen erfüllen, lohnt es sich sicher sich mal damit zu beschäftigen.
Die von dir angeführten Probleme scheinen aber eher mit der Struktur der Anwendung oder der Daten zusammen zu hängen. Wenn alle Daten aus einer Tabelle der Datenbank abgefragt werden, geht das nicht schneller als das Lesen einer Datei. Eine Datenbankanwendung solltest du vieleicht von Grund auf neu entwickeln.

Hier noch Beispielcode zu meinem Lösungsvorschlag mit einer komprimierten Datei:
Delphi-Quellcode:
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;
  Mit Zitat antworten Zitat