Autor Beitrag
P@u1
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 117



BeitragVerfasst: Do 15.04.10 18:14 
Hallo DF,

wie speichere ich am besten sehr viele (mehrere Millionen) Wahrheitswerte in eine Datei ab?

Habe bisher die Idee gehabt als 1en und 0en in ne text datei zu packen oder evtl die 1en und 0en vorher noch ins 16 oder 10er system umzuwandeln (um die dateigröße zu reduzieren)
Das einlesen wird dadurch aber wahrscheinlich relativ langsam.

Wenn ich das als 1en und 0en in ne text datei schreibe hat die die 8-fache größe von dem was ich erwartet hätte (ich denke er nimmt ein byte für jedes bit...)

Also wie sollte ich am besten vorgehen?

Hoffe das ist hier richtig und kommt nicht in datenbank rein^^

Edit: Wichtig ist auch noch, wie und in was für ein Objekt ich das am besten reinlese.
Edit2: Falls das wichtig ist: Es geht um ca. 26 Millionen Wahrheitswerte


Zuletzt bearbeitet von P@u1 am Do 15.04.10 18:21, insgesamt 1-mal bearbeitet
jfheins
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 918
Erhaltene Danke: 158

Win 10
VS 2013, VS2015
BeitragVerfasst: Do 15.04.10 18:20 
Ein Byte pro Wahrheitswert ist voll okay. Eine 2 Megabyte-Datei ist heutzutage nichts besonderes mehr ;)

Du kannst natürlich auch ein bit pro Wert nehmen, das ist dann halt so klein wie möglich. Aber auch aufwändiger zu lesen und zu schreiben (Klassischer Space vs. Time Tradeoff)
P@u1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 117



BeitragVerfasst: Do 15.04.10 18:22 
wie kann ich das denn im bit-format abspeichern?
hätte lieber ca.3 MB größe als 26 MB
jfheins
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 918
Erhaltene Danke: 158

Win 10
VS 2013, VS2015
BeitragVerfasst: Do 15.04.10 18:25 
Wie hast du die Daten denn vorliegen? Als Boolean Array?
P@u1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 117



BeitragVerfasst: Do 15.04.10 18:27 
ich hab sie noch gar nicht vorliegen, ich generiere die selbst, aber boolean-array habe ich bisher benutzt.
wenn es nen besseres format gibt, würde ich evtl auch das nehmen.

Wichtig zu wissen wäre dann noch wie ich das am besten laden kann, also ich kenne bisher leider nur den weg über eine stringlist o.ä. die sachen reinzuladen und dann zu konvertieren, wäre besser es direkt in ein bool-array wieder reinladen zu können

Vielen Dank für deine Hilfe!
jfheins
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 918
Erhaltene Danke: 158

Win 10
VS 2013, VS2015
BeitragVerfasst: Do 15.04.10 18:39 
Dann geht das ungefähr so:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure SaveToFile(const array)
var Bytearray: Array of Byte;
begin
  setlength(Bytearray, Ceil(length(array)/8));
  for i := 0 to high(arraydo
  begin
    if array[i] then
      Bytearray[i div 8] = Bytearray[i div 8or (1 shl (i mod 8));
  end;
  // Speichere das Bytearray, und die Länge des richtigen Arrays
end;

Das ist jetzt nur so schnell hingeschriben, es geht bestimmt auch noch etwas schneller (Über das bytearray iterieren und immer gleich 8 Bools zusammen speichern) ist dann aber komplizierter, falls die Anzahl deiner Wahrheitswerte nicht glatt durch 8 teilbar ist.
ALF
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1085
Erhaltene Danke: 53

WinXP, Win7, Win10
Delphi 7 Enterprise, XE
BeitragVerfasst: Do 15.04.10 18:40 
Hi, Du kannst doch auch das als 32, 64 bit Werte speichern und beim auslesen wieder die einzelnen bits in Boolean werte lesen. Nachteil, du kannst unter Umständen die Werte in der Text Datei nicht entziffern.

Gruss Alf

_________________
Wenn jeder alles kann oder wüsste und keiner hätt' ne Frage mehr, omg, währe dieses Forum leer!
P@u1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 117



BeitragVerfasst: Do 15.04.10 18:48 
user profile iconjfheins hat folgendes geschrieben Zum zitierten Posting springen:
Dann geht das ungefähr so:
ausblenden Delphi-Quelltext
1:
2:
      if array[i] then
        Bytearray[i div 8] = Bytearray[i div 8or (1 shl (i mod 8));



kanns sein, dass vor dem gleich ein doppelpunkt fehlt? wenn nicht, dann versteh ich das schon von der syntax nicht, ansonsten versteh ich einige befehle davon auch nicht, aber ich werds mir gleich nochmal genauer angucken

@ALF: Das sagt mir leider nicht so viel, ich weiß weder wie das geht, noch was das bringt :D

Edit: Das größte Problem ist, ich weiß bisher nur wie man dateien als .txt speichert. ich werd aber jetzt mal nen bischen suchen wie das mit anderen formaten geht
jfheins
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 918
Erhaltene Danke: 158

Win 10
VS 2013, VS2015
BeitragVerfasst: Do 15.04.10 19:02 
ja, das ist eine Zuweisung (also muss ein Doppelpunkt hin) - aber der Code wird so wie er da steht eh nicht kompilieren. Vielmehr ist es ein in Pseudocode gegossener Gedankengang ;)
P@u1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 117



BeitragVerfasst: Do 15.04.10 19:04 
wie und in welchem format speicher ich dann denn das byte array am besten ab?
Edit: Ceil und shl sind mir unbekannt
ALF
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1085
Erhaltene Danke: 53

WinXP, Win7, Win10
Delphi 7 Enterprise, XE
BeitragVerfasst: Do 15.04.10 19:09 
im Prinzip das was @jfheins schon geschrieben hat.
Beispiel:
1010001001011001011101011110011 das sind 32 boolean Werte = binärzahl
12113135363 entspricht einem Oktalwert
1361885939 oder Dezimalzahl
512CBAF3 bzw Hexwert

Du siehst damit kannst Du dann platzt in der Datei sparen.
Um das so umzuwandeln muss ich selbst mal schauen, schon lange her :?
Gruss Alf

_________________
Wenn jeder alles kann oder wüsste und keiner hätt' ne Frage mehr, omg, währe dieses Forum leer!
P@u1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 117



BeitragVerfasst: Do 15.04.10 19:37 
heißt 32 bzw 64 bit dann das ich die zahl ins 32er /64er system umwandle? soviele buchstaben gibts dann doch gar nicht :D

das hatte ich am anfang ja auch schon vorgeschlagen,
aber dass wird das einlesen verlangsamen (muss noch konvertiert werden).

Und Soll das dann in einer txt datei gespeichert werden oder besser was anderes?
ALF
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1085
Erhaltene Danke: 53

WinXP, Win7, Win10
Delphi 7 Enterprise, XE
BeitragVerfasst: Do 15.04.10 19:42 
Schau mal hier www.delphipraxis.net/topic41913,15.html
und hier ist auch noch was Umwandlung von Dezimalzahlen in andere Zahlensysteme
user profile iconP@u1
Zitat:
aber dass wird das einlesen verlangsamen

Ich bitte Dich, da gibt es komplizierteres, was echt Zeit kostet :wink:

Und abspeichern in einer Textdatei, so kannst Du den String auch gleich wieder nutzen.

Gruss Alf

_________________
Wenn jeder alles kann oder wüsste und keiner hätt' ne Frage mehr, omg, währe dieses Forum leer!
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Do 15.04.10 19:51 
Mal ein anderer Ansatz:

Schreib die Daten so wie sie kommen, von mir aus auch als Bytes, und jage das Ganze durch einen CompressionStream (zlib also).
Solange irgendwelche Muster (=mehrere gleiche Werte o.ä.) drin sind, ist das effektiver als sich unglaublich komplizierte Algorithmen zur Datenverpackung zu bauen.
Zumal du früher oder später dann eh bei Run-Length-Encoding landen würdest, wenn du weiter optimierst ;)

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Do 15.04.10 20:09 
Moin!

Suchst du sowas? ;)
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
unit BitVektor;

interface

uses
  SysUtils, Classes;

const
  MAGIC = AnsiString('NBVF');

type
  TBitVektor = class(TObject)
  private
    FCapacity: Integer;
    FData: array of LongWord;
    procedure SetCapacity(const Value: Integer);
    function GetBit(const AIndex: Integer): Boolean;
    procedure SetBit(const AIndex: Integer; const Value: Boolean);
  public
    constructor Create(const InitialCapacity: Integer = 32);
    destructor Destroy; override;
    property Capacity: Integer read FCapacity write SetCapacity;
    property Bit[const AIndex: Integer]: Boolean read GetBit write SetBit;
    procedure Clear;
    procedure WriteToStream(AStream: TStream);
    procedure ReadFromStream(AStream: TStream);
    procedure SaveToFile(const AFileName: String);
    procedure LoadFromFile(const AFileName: String);
  end;

implementation

{ TBitVektor }

procedure TBitVektor.Clear;
  var
    i: Integer;
begin
  for i := 0 to High(FData) do
    FData[i] := 0;
end;

constructor TBitVektor.Create(const InitialCapacity: Integer = 32);
begin
  inherited Create;
  SetCapacity(InitialCapacity); // Speicher für Daten holen
end;

destructor TBitVektor.Destroy;
begin
  FData := NIL// Speicher freigeben
  inherited;
end;

function TBitVektor.GetBit(const AIndex: Integer): Boolean;
begin
  Result := (FData[AIndex shr 5and (1 shl (AIndex and 31))) <> 0;
end;

procedure TBitVektor.LoadFromFile(const AFileName: String);
  var
    FS: TFileStream;
begin
  FS := TFileStream.Create(AFileName,fmOpenRead or fmShareDenyWrite);
  try
    ReadFromStream(FS);
  finally
    FS.Free;
  end;
end;

procedure TBitVektor.ReadFromStream(AStream: TStream);
  var
    FileMagic: AnsiString;
    NewCapacity: Integer;
begin
  SetLength(FileMagic,4);
  AStream.Read(PAnsiChar(FileMagic)^,4);
  if (FileMagic = MAGIC) then begin
    AStream.Read(NewCapacity,4);
    SetCapacity(NewCapacity);
    AStream.Read(FData[0],Length(FData)*4);
  end
  else
    raise Exception.Create('Format-Fehler!');
end;

procedure TBitVektor.SaveToFile(const AFileName: String);
  var
    FS: TFileStream;
begin
  FS := TFileStream.Create(AFileName,fmCreate);
  try
    WriteToStream(FS);
  finally
    FS.Free;
  end;
end;

procedure TBitVektor.SetBit(const AIndex: Integer; const Value: Boolean);
begin
  if Value then
    FData[AIndex shr 5] := FData[AIndex shr 5or  (1 shl (AIndex and 31))
  else
    FData[AIndex shr 5] := FData[AIndex shr 5and NOT (1 shl (AIndex and 31));
end;

procedure TBitVektor.SetCapacity(const Value: Integer);
begin
  if (Value > 0then begin
    FCapacity := Value;
    SetLength(FData,((FCapacity +31shr 5));
  end
  else
    raise Exception.Create('TBitVektor.Capacity muss >0 sein!');
end;

procedure TBitVektor.WriteToStream(AStream: TStream);
begin
  AStream.Write('NBVF',4);
  AStream.Write(FCapacity,4);
  AStream.Write(FData[0],Length(FData)*4);
end;

end.
Benutzung im Demo-Projekt.

cu
Narses
Einloggen, um Attachments anzusehen!
_________________
There are 10 types of people - those who understand binary and those who don´t.
P@u1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 117



BeitragVerfasst: Do 15.04.10 20:12 
Wie das grundsätzlich mit den Systemen funktioniert wusste ich schon, ich hatte mich nur gefragt, ob 32 bit 32er system und 64 bit 64er system bedeutet.
64er system finde ich nur komisch, weil dafür die buchstaben nicht ausreichen.

ich habe jetzt vorerst die datei nochmal mit den 0en und 1en als txt gelassen, ist dann rund 26 MB groß.
Mit der Datei wollte ich dann ein paar tests machen.
Wenn ich die Datei in eine Stringlist reinlade, dann ist das komischer weise sofort fertig (kann es sein, dass das dann nicht "wirklich" reingeladen wird, sondern nur die stringlist sich abspeichert, von wo er die infos holen soll oder so?
Und wenn ich das dann in ein Array of Boolean reinladen will dauert das sehr lange.
Ich hab testweise erstmal 10000 array werte reingeladen (von ca. 26 Millionen) und das hat schon über eine sekunde gedauert.
Kann man das nicht irgendwie schneller machen bzw. wieso dauert das überhaupt so lange?
Xentar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2077
Erhaltene Danke: 2

Win XP
Delphi 5 Ent., Delphi 2007 Prof
BeitragVerfasst: Do 15.04.10 20:21 
Du könntest uns mal zeigen, WIE du die Daten einliest.

_________________
PROGRAMMER: A device for converting coffee into software.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Do 15.04.10 20:22 
Moin!

user profile iconP@u1 hat folgendes geschrieben Zum zitierten Posting springen:
ich habe jetzt vorerst die datei nochmal mit den 0en und 1en als txt gelassen, ist dann rund 26 MB groß.
Die Klasse oben macht das mit ca. 3MB und in kaum messbarer Zeit. :D Dafür ist der Zugriff auf einzelne Bits halt nicht so schnell, aber man kann eben nicht alles haben. :nixweiss: Ist für wenig Zugriffe und schnellen I/O gemacht.

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
P@u1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 117



BeitragVerfasst: Do 15.04.10 20:29 
@narses: ich bin leider noch nicht dazu gekommen, mir die klasse anzugucken, werde ich aber später/morgen noch machen.
Und ich muss darauf sehr oft zugreifen, also ist das wahrscheinlich nicht so besonders gut geeignet.

Jetzt dauert es komischerweise nicht mehr lange, sondern gibt eine zugriffsverletzung
wie ich es einlese:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
var
  Form1: TForm1;
  b: Array[1..25000000of Boolean;

procedure TForm1.Button2Click(Sender: TObject);
var
  sl: TStringList;
  i: Longint;
begin
  sl:=TStringList.Create;
  sl.LoadFromFile(OpenDialog1.FileName);
  for i := 1 to 20000000 do
  begin
    try
    if sl[0][i]='1' then
    b[i]:=true
    else
    b[i]:=false;
    except

    ShowMessage(inttostr(i));
    sl.free;
    exit;

    end;
  end;
  sl.Free;

end;


die try/except sachen hab ich eingefügt um rauszufinden, bei welchem wert der fehler kommt, er kommt bei i=1566105
ist da vielleicht der integer zuende oder so? (hab jetzt extra integer durch longint ersetzt)
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Do 15.04.10 20:41 
Moin!

user profile iconP@u1 hat folgendes geschrieben Zum zitierten Posting springen:
Und ich muss darauf sehr oft zugreifen, also ist das wahrscheinlich nicht so besonders gut geeignet.
OK, dann nagel doch einfach gleich das Array auf die Platte. :nixweiss:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var
  b: Array[0..25000000of Boolean;
  FS: TFileStream;

// Stream aufmachen
FS.Write(b[0],Length(b)*SizeOf(Boolean));

FS.Read(b[0],Length(b)*SizeOf(Boolean));
Ist nicht sparsam mit dem Plattenplatz, aber schnell und einfach. :idea:

cu
Narses

//EDIT: Array-Basis auf 0 gesetzt

_________________
There are 10 types of people - those who understand binary and those who don´t.


Zuletzt bearbeitet von Narses am Do 15.04.10 20:46, insgesamt 1-mal bearbeitet