Binär-Daten einlesen



  • Hi zusammen ich versuche Binärdaten einzulesen und möchte aber am Anfang eine gewisse Anzahl Bytes überspringen! Sprich ich will aus nem File Byte z.B. ab Byte 48 einlesen. Wie mache ich das am besten?
    Wäre schön wenn mir das einer erklären könnte.

    Vielen Dank schon im Voraus



  • deinstreamobjekt.seekg(48);
    // jetzt lesen
    




  • Morgen,

    das kannst du machen, indem du den Dateizeiger entsprechend positionierst:

    ifstream fileIn("foobar.txt");
        //dateizeiger 48 Bytes weitersetzen, beginnend vom anfang der Datei
        fileIn.seekg(48, ios_base::beg);
    

    mfg
    v R

    [edit]
    zu spaet 😉
    [/edit]



  • 😮 😕 😮
    OK hab grad mal ein wenig in die MSDN geschaut um nach den Begriffen (die mir nahezu alle neu sind) zu suchen. Daraus hab ich jetzt mal folgendes gemacht.

    char ch;
    
       ifstream tfile( "D:\\Test.wav", ios::binary | ios::nocreate );
       if( tfile ) {
          tfile.seekg( 48 );      // Seek 48 bytes in (past salary)
          while ( tfile.good() ) { // EOF or failure stops the reading
             tfile.get( ch );
             if( !ch ) break; // quit on null
          }
       }
       else {
          MessageBox("ERROR: Cannot open file");
       }
    

    jetzt sollte doch eigentlich ab dem 49.Byte meine Daten in ch stehen haben, oder? mein debugger sagt mir dann aber

    ch = 0''

    kannst du mir deinen Post bzw. die Idee die dahinter steckt genauer erklären?



  • OK hab mir nochmal den FAQ beitrag angeschaut, und hab jetzt schon ein wenig mehr verstanden, so von wegen Streamobjekt und so. Ich versuch folgendes:

    fstream FileBin("d:\\test.wav", ios::in|ios::out|ios::binary);
    	if (FileBin.is_open()) 
    	{ 
    	    // 1. Dateigröße bestimmen. 
    	    FileBin.seekg(0, ios::end); 
    	    unsigned long FileSize = streamoff(FileBin.tellg()); 
    	    FileBin.seekg(0, ios::beg); 
    
    	    // 2. Puffer anlegen und Datei einlesen. 
    	    char* pBuffer = new char[FileSize];
    		FileBin.seekg(48);
    	    FileBin.read(pBuffer, FileSize-48); 
    
    	    // Nachher wieder aufräumen. 
    	    delete [] pBuffer; 
    	}
    

    aber er geht mir nie in die IF - Abfrage rein.

    Für was brauch ich using namespace std; da bekomm ich immer

    Compiler schrieb:

    error C2871: 'std' : does not exist or is not a namespace



  • bist du sicher, dass du c++ compilierst?
    mach mal nen .cpp file.

    http://www.cs.colorado.edu/~main/vccode.html

    ps: zeig mal die headerfiles, die du includierst.



  • na klar bin ich mir sicher dass ich C++ kompilier! Hab auch schon den Fehler gefunden. Das open hat nicht geklappt und drum ist er auch nicht in die if(isOpen()) gegangen. Wie kann ich jetzt jedes Byte als long int in ein array speichern?

    length=strlen(pBuffer); 
    		for(int i=length-1; i>=0; i--) 
    		{ 
    			if(pBuffer[i]!='0')
    				decimal=decimal+(1<<(length-i-1)); 
    		}
    

    So mach ich mir meine dezimalzahl, aber wie speichere ich das jetzt in ein Array? (Am besten so dass ich nacher den integerWert mit der Bytenummer ansprechen kann.
    Vielen Dank euch allen.



  • Deine Umwandlung in eine dezimalzahl ( was immer du auch darunter verstehst ) kann ich wirklich nicht nachvollziehen.

    length=strlen(pBuffer);
    for(int i=length-1; i>=0; i--)
    {
    if(pBuffer[i]!='0')
    decimal=decimal+(1<<(length-i-1));
    }

    Wenn ich den Thread richtig verstanden habe dann geht es dir darum eine Wave- datei auszulesen und das ist eine binärdatei, da kommst du mit stringfunktionen wie strlen nicht weit.
    Kurt



  • OK ich habe meinen binären Krämpel nun in meinem Buffer. Ich muss nun einige FFTs DFTs etc machen und dazu brauch ich von jedem einzelnen Byte den dezimalwert. Sprich wenn ich 1 Byte einlese und bekomme 00001010 dann will ich die 10 in ein int array speichern.
    Ich hab grad versucht ein Byte einzulesen und dann in dezimal zu konvertieren und bekomm 16772866 raus das sind aber doch 3Byte. Wüsste nicht wie man diese Zahl in einem Byte darstellen kann. vielleicht hier nochmal mein Source:

    {
    //	using namespace std;
    	unsigned long decimal=0;
    	int length = 0;
    
    	fstream FileBin("d:\\test.wav", ios::in|ios::out|ios::binary);
    	if (FileBin.is_open()) 
    	{ 
    	    // 1. Dateigröße bestimmen. 
    	    FileBin.seekg(0, ios::end); 
    	    unsigned long FileSize = streamoff(FileBin.tellg()); 
    	    FileBin.seekg(0, ios::beg); 
    
    	    // 2. Puffer anlegen und Datei einlesen. 
    	    char* pBuffer = new char[FileSize];
    		FileBin.seekg(45);
    	    FileBin.read(pBuffer,1); 
    
    		unsigned long test= binToDec(pBuffer);
    	    // Nachher wieder aufräumen. 
    	    delete [] pBuffer; 
    	}
    }
    
    unsigned long CIhwfView::binToDec(char *binary) 
    { 
    	int length=strlen(binary), decimal=0; 
    	for(int i=length-1; i>=0; i--) 
    	{ 
    		if(binary[i]!='0')
    			decimal+=(1<<(length-i-1)); 
    	} 
    	return(decimal); 
    }
    

    wie bekomm ich das hin??



  • ein einfacher cast tuts schon

    for ( int i = 0; i < FileSize; i++ ) {
       unsigned long  decimal = (unsigned long)(unsigned char)binary[i];
    }
    

    Kurt



  • OK stimmt das konvertieren klappt so genauso, doch mir ist immernoch nicht klar wenn ich jetzt folgendes hab:

    unsigned long decimal=0;
    	int length = 0;
    
    	fstream FileBin("d:\\test.wav", ios::in|ios::out|ios::binary);
    	if (FileBin.is_open()) 
    	{ 
    	    // 1. Dateigröße bestimmen. 
    	    FileBin.seekg(0, ios::end); 
    	    unsigned long FileSize = streamoff(FileBin.tellg()); 
    	    FileBin.seekg(0, ios::beg); 
    
    	    // 2. Puffer anlegen und Datei einlesen. 
    	    char* pBuffer = new char[8];
    		FileBin.seekg(m_lEingabe);
    	    FileBin.read(pBuffer,1);
    

    Was steht jetzt in pBuffer (Format mäßig) wie bekomme ich es hin, dass das was in die Art 01010011 drin steht? 😕 weil mit dem eben geposteten Code bekomm ich dezimal immer 0 und in pBuffer steht nahezu nur Schrott!
    Das da sind Daten ausm Hexeditor:

    RIFFWAVEfmt dataz

    so und wenn ich jetzt eines der Bytes einlese, in denen solch ein Buchstabe drin steht wie in obigem quote dann bekomm ich als ausgabe von meinem pBuffer das zeichen und danach Schrott. z.B. Byte40 (das z bei dataz)

    zÍÍÍÍÍÍÍ

    HILFE 😕



  • OK ich glaub fast das ist ein MFC Problem, ich werde mal im MFC-Forum fragen.

    Vielen Dank euch allen! 🙂



  • Wie gesagt ein Wave-file enthält binäre daten. ( nur im Header steht etwas text zb. RIFF WAVE ... ). Ab einem bestimmten Offset ( 48 ? ) stehen dann die reinen Sample Daten im Binär format. Daher kann dein Hex-Editor auch nicht alle zeichen anzeigen. Der interpretiert nur jedes byte als char und wenn es ein druckbares zeichen ist dann zeigt er dir auf der rechten Seite das entsprechende Ascii-zeichen.
    Der von mir früher gezeigte cast von char -> unsigned char -> unsigned long funktioniert auch nur dann wenn deine .wav datei mono- daten mit 8-bit samples enthält. Hast du 16 bit Samples schaut die umrechnung schon wieder anders aus. dann musst du immer 2 bytes als unsigned short interpretieren.
    Kurt



  • Aehm...wie kommt ihr darauf, dass in der Datei die Daten in Binaer (01) stehen?

    Du lest da Bytes ein! Willst du unbedingt 0en und 1sen, dann musst du schauen,
    welche Bits wo gesetzt sind bzw. nicht gesetzt sind und eine entsprechende
    Ausgabe machen.

    Nach dem Lesen aus der Datei, habt ihr aber nicht die Daten in Binaerschreibweise
    eingelesen.

    mfg
    v R



  • Hallo polofreak,

    also wenn ich das richtig verstanden habe, dann willst du eine wav-datei einlesen und die werte dann bearbeiten. (Info zum Aufbau einer Wav-datei:
    http://www.aculab.com/support/ting/an-wav.html)

    Also wenn du nur die Werte brauchst, dann würd ich die ersten 8192 Character aus der Datei erst mal nich einlesen. Soweit ich weiss, steht da nämlich lauter Header-Info drin, die Sampling-Rate, die Anzahl an Kanälen, usw.
    Die eigentlichen Daten dann in einen charbuffer einlesen. Und mit folgender Funktion bearbeiten:

    ......
    signed short
    ByteRangeToInt16
    (
       unsigned char* t_data,
       unsigned long t_offset
    )
    { 
       short res;
       res = t_data[ t_offset + 1 ];
       res = ( res<<8 );
       res += t_data[ t_offset ];
       return res;
    }
    

    Aufruf der Funktion erfolgt so:
    (tmpData ist der charbuffer)

    for( unsigned long i=0; i < m_Length; i++ )
             {
    				valData[i] = ByteRangeToInt16( tmpData, i*2)/32768.0;
             }
    

    So, ich hoffe, das hilft dir weiter.

    Gruß,
    Amalthea



  • virtuell Realisticer schrieb:

    Aehm...wie kommt ihr darauf, dass in der Datei die Daten in Binaer (01) stehen?

    Mir ist klar dass da keine 01 strings stehen nur wie bezeichnest du eben solche daten die in einer "binären datei" stehen ?
    Kurt



  • Hi! Sorry wenn ich jetzt hier herein platze, aber meine Frage passt hier gut rein und ich denke keiner würde es mögen wenn ich noch nen Thread dafür eröffne... 😉
    Also:
    Ich habe (wie auch in dem Listing in der oben geposteten FAQ, das wo ein struct "PERSON" binär gespeichert und gelesen wird (das Listing kompiliert übrigens unter Dev-CPP nicht, obwohl ich natürlich die Headers included habe...)) ein struct und eine write / read funtkion, sowie eine Funktion, die alles mit sauberen Werten initialisiert:

    struct A
    {
        int a;
        int b;
        std::string dummy;
    }
    
    void write(struct A *inst, std::string filename)
    {  
       std::fstream file(filename.c_str(), ios_base::out | ios::binary);
       if(!file)
          exit(0);
       file.write((const char*)&inst, sizeof(inst));
       //ich kann das & vor inst auch weglassen, ändert nichts
       file.close();
    }
    
    void read(struct A *read_to, std::string filename)
       std::fstream file(filename.c_str(), ios_base::in | ios::binary);
       if(!file)
          exit(0);
       file.read((char*)&read_to, sizeof(read_to));
       file.close();
    }
    
    void fill(struct A *fill)
    {
       fill->a = 0;
       fill->b = 0;
       fill->dummy = "";
    }
    

    Das wird folgendermaßen implementiert:

    //includes...
    int main()
    {
       A source;
       fill(&instance);
       B dest;
       fill(&dest);
    
       std::string filename = "my_file.x";
       write(&source, filename);
       read(&dest, filename);
    
       //ausgabe von dest...
    }
    

    Jetzt werden leider nur die Werte aus fill() ausgegeben... Was mache ich falsch? Würde mich sehr über Antworten freuen! 🙂

    btw: Ich hasse einfach binäre dateien^^



  • ZuK schrieb:

    virtuell Realisticer schrieb:

    Aehm...wie kommt ihr darauf, dass in der Datei die Daten in Binaer (01) stehen?

    Mir ist klar dass da keine 01 strings stehen nur wie bezeichnest du eben solche daten die in einer "binären datei" stehen ?
    Kurt

    Die Daten werden Byteweise gelesen, daran aendert sich nichts, wohl aber aendert sich die Art und Weise, wie spezielle Character interpretiert werden.

    mfg
    v R



  • some_binary_file schrieb:

    Hi! Sorry wenn ich jetzt hier herein platze, aber meine Frage passt hier gut rein und ich denke keiner würde es mögen wenn ich noch nen Thread dafür eröffne... 😉
    Also:
    Ich habe (wie auch in dem Listing in der oben geposteten FAQ, das wo ein struct "PERSON" binär gespeichert und gelesen wird (das Listing kompiliert übrigens unter Dev-CPP nicht, obwohl ich natürlich die Headers included habe...))

    Meine Glaskugel verweigert mir die Auskunft auf die Frage, was denn als
    Fehlermeldung ausgegeben wird.

    ein struct und eine write / read funtkion, sowie eine Funktion, die alles mit sauberen Werten initialisiert:

    struct A
    {
        int a;
        int b;
        std::string dummy;
    }
    
    void write(struct A *inst, std::string filename)
    {  
       std::fstream file(filename.c_str(), ios_base::out | ios::binary);
       if(!file)
          exit(0);
       file.write((const char*)&inst, sizeof(inst));
       //ich kann das & vor inst auch weglassen, ändert nichts
       file.close();
    }
    
    void read(struct A *read_to, std::string filename)
       std::fstream file(filename.c_str(), ios_base::in | ios::binary);
       if(!file)
          exit(0);
       file.read((char*)&read_to, sizeof(read_to));
       file.close();
    }
    
    void fill(struct A *fill)
    {
       fill->a = 0;
       fill->b = 0;
       fill->dummy = "";
    }
    

    Das wird folgendermaßen implementiert:

    //includes...
    int main()
    {
       A source;
       fill(&instance);
       B dest;
       fill(&dest);
    
       std::string filename = "my_file.x";
       write(&source, filename);
       read(&dest, filename);
    
       //ausgabe von dest...
    }
    

    Jetzt werden leider nur die Werte aus fill() ausgegeben... Was mache ich falsch?

    Der Dateizeiger zeigt auf das Ende der Datei, folglich kannst du den Inhalt
    der Datei nicht anzeigen, ohne den Dateizeiger zurueck auf den Anfang der
    Datei zu setzen.

    mfg
    v R


Log in to reply