große datenmengen in c++ speichern



  • semi schrieb:

    in unserer semiarbeit lesen wir wavedateien aus, um die Daten später noch nachzubearbeiten. es wäre also wichtig, dass diese gut ansprechbar sind, z.b. durch indizes wie bei den arrays.

    Was machst du denn mit diesen Wave-Dateien genau? Normalerweise stehen die Daten dort schon in einer brauchbaren Form drin (als Binärdatei).

    und: sind die daten nicht, wenn man ein array anlegt, auch im arbeitsspeicher oder lässt sich dieser noch direkt ansprechen?

    Ja, das Array ist auch im Arbeitsspeicher - aber vermutlich hast du einfach nur die Kapazität des Programmstacks ausgelastet. Wenn du unbedingt mit nackten Arrays arbeiten willst, lagere sie auf den Heap (Zeiger und new[]/delete[] - am besten gekapselt hinter einem STL Container s.u.) oder den Datenblock (static/global) aus, da steht idR mehr Platz zur Verfügung.

    @cstoll:
    heißt das, dass vectors und deques so etwas wie größere/flexiblere arrays sind?
    das wäre ja für die aufgabe ideal, außerdem müssen die daten ja nicht das programmende überleben.

    Im Prinzip ja - vor allem lässt sich ihre Größe zur Laufzeit anpassen, wenn du das benötigst. Außerdem steht dann auf dem Stack nur eine recht kleine Verwaltungsstruktur, während die Nutzdaten auf dem wesentlich größeren Heap gelagert werden.
    (du kannst natürlich auch die Daten gar nicht im Programm speichern, sondern per seekg() durch deine Eingabedatei pflügen)



  • Stefan schrieb:

    Wenn es ums Messwerte aufzeichnen geht, würde ich es in einem Tab-getrennten Spreadsheet speichern.

    Was bedeutet denn das? Hab ich noch nie gehört, klingt aber interessant 🙂



  • ich muss auf die daten wie gesagt leicht zugreifen können. in einer binärdatei oder einer Tab-getrennten datei kann man ja glaub ich nicht einfach den z.b. 1734. datensatz auslesen. ein array wär da immer noch die beste lösung.
    ich versuchs jetzt mit der variante:

    int *Lotto = 0;      // Zeiger definieren und sichern
    Lotto = new int [6]; // Array mit sechs Elementen erzeugen
    for (i=0; i<6; i++)  // Array durchlaufen
    {
         Lotto[i] = rand() % 49 + 1; // Lottozahl erzeugen
    }
    delete[] Lotto;      // Freigabe des Speichers
    Lotto = 0;           // Zeiger sichern
    

    und wenn das nicht geht mit vectors und deques.

    gr david



  • semi schrieb:

    ich muss auf die daten wie gesagt leicht zugreifen können. in einer binärdatei oder einer Tab-getrennten datei kann man ja glaub ich nicht einfach den z.b. 1734. datensatz auslesen.

    Klar kannst du das 🙂 Wenn du den 1734ten Datensatz brauchst, setzt du den Dateizeiger einfach auf 1734*sizeof(datensatz) und liest den Datensatz ein. Geht natürlich nur, wenn die Datensätze eine fixe Länge haben, was bei shorts aber ja der Fall ist. Gerade in wav-Dateien sind die Daten ja schon sequentiell gespeichert, du musst bei der Berechnung des Dateizeigers einfach nur noch den Header überspringen.
    Falls sich das mit deinen Anforderungen verträgt, kannst du auch einfach immer nur einen Teil der Daten im Arbeitsspeicher behalten, bei Bedarf einen neuen Block aus der Datei nachholen.



  • Klar kannst du auf das Nte Element zugreifen wenn du weißt wie groß deine Datensätze sind 😉
    Und zum Format http://de.wikipedia.org/wiki/CSV_(Dateiformat)



  • Wenn du vorher nicht weißt wie groß deine Daten sind (also falls der Arbeitsspeicher evtl nicht ausreicht), kannst du dir auch eine Verwaltungsklasse dafür schreiben. Wenn genug Platz im RAM ist, kann sie die Daten komplett einlesen, wenn nicht, holt sie die Daten aus der Datei. Oder halt Blockverwaltung. Oder so. Das wäre auch sinnvoll, wenn dein Programm auch auf Rechnern laufen soll, die ein bisschen lau an Arbeitsspeicher sind, wav-Dateien können u.U. ja doch recht groß werden..



  • Badestrand schrieb:

    Stefan schrieb:

    Wenn es ums Messwerte aufzeichnen geht, würde ich es in einem Tab-getrennten Spreadsheet speichern.

    Was bedeutet denn das? Hab ich noch nie gehört, klingt aber interessant 🙂

    Eigentlich ist es eine Tabelle in Form eines gewöhnlichen Textfiles. Daten in dieser Form lassen sich z.B. sehr einfach als Excel-Tabelle importerieren.



  • semi schrieb:

    ich versuchs jetzt mit der variante:

    Lass das lieber bleiben und geh gleich zu vector/deque über - ist einfacher zu handhaben und auf die Dauer auch eleganter.



  • wir haben das array jetzt mit der neuen variante groß genug gekriegt. das problem ist jetzt nur noch das auslesen aus der wavedatei, weil wir uns mit zeigern nicht auskennen. wäre es möglich ein beispiel zu posten, wie man eine binäre datei (.wav) gezielt ausliest?

    @cstoll:
    da das mit dem array geht, lassen wir es erstmal so und versuchen das auslesen der datei hinzukriegen. dann können wir uns auch mit vectors beschäftigen 😉



  • Auslesen kannst du die Daten (am Stück oder in kleineren Abschnitte) mit einem fstream und dessen read() oder readsome() Methode. Wenn du gezielt an einer bestimmten Position anfangen willst, kannst du mit seekg() dorthin springen (da gibtst du den Offset in Byte vom Dateianfang an).



  • Mit was liest du denn die Datei ein? Bei std::ifstream gibts jedenfalls die Methode "read", die liest dir die rohen Daten ein.



  • wir lesen jetzt mit fstream aus der wavedatei aus. doch irgendwie scheint fstream probleme mit dem auslesen von zahlen zu haben...

    char ID[4];
        char ChunkSize;
        char Format[4];
        char Subchunk1ID[4];
        char Subchunk1Size;
        char AudioFormat;
        char NumChannels;
        char SampleRate;
        char ByteRate;
        char BlockAlign;
        char BitsPerSample;
        char Subchunk2ID[4];
        char Subchunk2Size;
    
        fstream f("audio.wav", ios::in|ios::binary);
    
        //Variablen mit Daten fuellen
        f.read(&ID[0], sizeof(ID[0]));
        f.read(&ID[1], sizeof(ID[1]));
        f.read(&ID[2], sizeof(ID[2]));
        f.read(&ID[3], sizeof(ID[3]));
        f.read(&ChunkSize, sizeof(ChunkSize));
        f.read(&Format[0], sizeof(Format[0]));
        f.read(&Format[1], sizeof(Format[1]));
        f.read(&Format[2], sizeof(Format[2]));
        f.read(&Format[3], sizeof(Format[3]));
        f.read(&Subchunk1ID[0], sizeof(Subchunk1ID[0]));
        f.read(&Subchunk1ID[1], sizeof(Subchunk1ID[1]));
        f.read(&Subchunk1ID[2], sizeof(Subchunk1ID[2]));
        f.read(&Subchunk1ID[3], sizeof(Subchunk1ID[3]));
         f.read(&AudioFormat, sizeof(AudioFormat));
         f.read(&NumChannels, sizeof(NumChannels));
         f.read(&SampleRate, sizeof(SampleRate));
         f.read(&ByteRate, sizeof(ByteRate));
         f.read(&BlockAlign, sizeof(BlockAlign));
         f.read(&BitsPerSample, sizeof(BitsPerSample));
         f.read(&Subchunk2ID[0], sizeof(Subchunk2ID[0]));
         f.read(&Subchunk2ID[1], sizeof(Subchunk2ID[1]));
         f.read(&Subchunk2ID[2], sizeof(Subchunk2ID[2]));
         f.read(&Subchunk2ID[3], sizeof(Subchunk2ID[3]));
         f.read(&Subchunk2Size, sizeof(Subchunk2Size));
    

    die oben definierten variablen mussten wir alle auf char setzten, weil er sonst "E2034 Konvertierung von 'int *' nach 'char *' nicht möglich in Funktion main() in Zeile 38" ausgab. Doch so werden die Zahlenwerte, wie z.b. ChunkSize nicht korrekt ausgegeben. Buchstabenwerte wie z.b. ID werden dagegen korrekt ausgegeben



  • Du kannst mit read() auch größere Variablen einlesen, mußt sie nur geeignet casten:

    int ChunkSize;
    f.read(reinterpret_cast<char*>(&ChunkSize),sizeof(ChunkSize));
    


  • ein riesengroßes dankeschön! jetzt gehts und wir können die daten auslesen.
    wir machen jetzt feierabend. danke an alle! 🙂



  • Und wenn du einen Array hast, kannst du auch einfach den Anfang, wo reingelesen werden soll angeben und dann die Anzahl der Items * die Größe jedes Items als Größe angeben:

    file_stream.write(reinterpret_cast<const char*>(&array[start_index]), sizeof(array[0]) * array_size);
    

    ... start_index ist meist 0 ...



  • Bei C-Arrays wie der ID geht auch f.read( ID, sizeof(ID) );



  • Danke für die tips aber wir stehen schon wieder von einem Problem...

    die headerdaten werden super ausgelesen, aber wir wissen nicht wie wir die für uns wichtigen daten danach auslesen können... wir haben folgendes versucht:

    short Data;
         //laenge enthält die anzahl der samples (werte) in der wavedatei
         int laenge;
    
         short *Data2;
         Data2=new short[laenge];
    
         for (int i = 0; i < laenge; i++)
         {
            f.read(reinterpret_cast<char*>(&Data), sizeof(Data));
            Data2[i]=Data;
          }
    

    danach sind in Data2 nur werte rund um +/-30000 enthalten, also keine korrekten datensätze...
    machen wir beim read() irgendwas falsch?



  • Erstmal hoffe ich, daß du irgendwo zwischen den Zeilen 3 und 5 auch einen Wert in die Variable 'laenge' eingetragen hast.

    Zweitens kannst du auch das Array auf einen Rutsch einlesen:

    short* Data = new[laenge];
    f.read(reinterpret_cast<char*>(Data),laenge*sizeof(short));
    

    Und drittens: sind alle eingelesenen Werte identisch? Wenn nein - hast du mal die angekommenen Daten mit dem Dateiinhalt verglichen?



  • semi schrieb:

    danach sind in Data2 nur werte rund um +/-30000 enthalten, also keine korrekten datensätze...

    Was ist daran nicht korrekt? Wenn du Werte zwischen 0 und 65.535 erwartest, musst du deine Variablen als 'unsigned short' deklarieren, dann werden sie anders interpretiert 🙂



  • endlich funktionierts...die komischen werte (immer entwender nah an 30000 oder -30000 und nicht dazwischen) lagen wohl am format der verwendeten wav-datei. funktionieren tuts nur bei pcm.

    @CStoll:
    1. aber natürlich
    2. danke für den tip, haben wir eingebaut

    @Badestrand:
    die werte sollen schon sowohl im minus- als auch im plusbereich liegen, nur dürfen sie nicht so auf kleinem bereich verteilt sein

    vielen dank für die viele hilfe!!! 🙂 🙂 🙂
    wir haben jetzt unsere wavedatei vollständig in ein großes array eingelesen und können die daten nun weiterverarbeiten.
    aber: stereo-wavedateien scheinen anders aufgebaut zu sein als mono-wavedateien. weiß jemand wie?


Anmelden zum Antworten