Autor |
Beitrag |
P@u1
      
Beiträge: 117
|
Verfasst: 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
      
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: 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 
      
Beiträge: 117
|
Verfasst: 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
      
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Do 15.04.10 18:25
Wie hast du die Daten denn vorliegen? Als Boolean Array?
|
|
P@u1 
      
Beiträge: 117
|
Verfasst: 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
      
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Do 15.04.10 18:39
Dann geht das ungefähr so:
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(array) do begin if array[i] then Bytearray[i div 8] = Bytearray[i div 8] or (1 shl (i mod 8)); end; 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
      
Beiträge: 1085
Erhaltene Danke: 53
WinXP, Win7, Win10
Delphi 7 Enterprise, XE
|
Verfasst: 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 
      
Beiträge: 117
|
Verfasst: Do 15.04.10 18:48
|
|
jfheins
      
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: 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 
      
Beiträge: 117
|
Verfasst: 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
      
Beiträge: 1085
Erhaltene Danke: 53
WinXP, Win7, Win10
Delphi 7 Enterprise, XE
|
Verfasst: 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 
      
Beiträge: 117
|
Verfasst: 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
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
      
Beiträge: 1085
Erhaltene Danke: 53
WinXP, Win7, Win10
Delphi 7 Enterprise, XE
|
Verfasst: 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
P@u1
Zitat: | aber dass wird das einlesen verlangsamen |
Ich bitte Dich, da gibt es komplizierteres, was echt Zeit kostet
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
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: 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
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Do 15.04.10 20:09
Moin!
Suchst du sowas?
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
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); end;
destructor TBitVektor.Destroy; begin FData := NIL; inherited; end;
function TBitVektor.GetBit(const AIndex: Integer): Boolean; begin Result := (FData[AIndex shr 5] and (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 5] or (1 shl (AIndex and 31)) else FData[AIndex shr 5] := FData[AIndex shr 5] and NOT (1 shl (AIndex and 31)); end;
procedure TBitVektor.SetCapacity(const Value: Integer); begin if (Value > 0) then begin FCapacity := Value; SetLength(FData,((FCapacity +31) shr 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 
      
Beiträge: 117
|
Verfasst: 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
      
Beiträge: 2077
Erhaltene Danke: 2
Win XP
Delphi 5 Ent., Delphi 2007 Prof
|
Verfasst: 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
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Do 15.04.10 20:22
Moin!
P@u1 hat folgendes geschrieben : | 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.  Dafür ist der Zugriff auf einzelne Bits halt nicht so schnell, aber man kann eben nicht alles haben.  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 
      
Beiträge: 117
|
Verfasst: 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:
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..25000000] of 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
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Do 15.04.10 20:41
Moin!
P@u1 hat folgendes geschrieben : | 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.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| var b: Array[0..25000000] of Boolean; FS: TFileStream;
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.
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
|
|