| Autor | 
Beitrag | 
P@u1 
        
 
Beiträge: 117 
 
 
 
 | 
Verfasst: Do 15.04.10 17: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 17:21, insgesamt 1-mal bearbeitet
 | 
 | 
jfheins 
        
 
Beiträge: 918 
Erhaltene Danke: 158 
 
Win 10 
VS 2013, VS2015 
 | 
Verfasst: Do 15.04.10 17: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 17: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 17:25 
 
Wie hast du die Daten denn vorliegen? Als Boolean Array? 
 
 | 
 | 
P@u1   
        
 
Beiträge: 117 
 
 
 
 | 
Verfasst: Do 15.04.10 17: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 17: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 17: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 17:48 
 
 | 
 | 
jfheins 
        
 
Beiträge: 918 
Erhaltene Danke: 158 
 
Win 10 
VS 2013, VS2015 
 | 
Verfasst: Do 15.04.10 18: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 18: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 18: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 18: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 18: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 18: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 19: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 19: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 19: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 19: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 19: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 19: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 19:46, insgesamt 1-mal bearbeitet
 | 
 |