Datein einlesen...



  • Hallo Leute,

    ich bin neu hier, und muß gleich zu Beginn mit einer Frage nerven.

    Ich versuche gerade Heightmaps für ein mit OpenGL generiertes Terran einzulesen.

    Ich habe es mit dem File Pointer probiert, wo ich bis auf Schwierigkeiten mit cout geschafft habe.

    Ein paar Leute meinten aber dass da C++ die neuere Methode ist, mit diesem hatte ich aber so meine Probleme, und hätte da einiges an Fragen.

    fstream file;
    string zeile;
    
    file.open("heightmap.bmp", fstream::in | fstream::binary);
    
    while(getline(file, zeile))
    {
        cout << getline(file, zeile) << endl;
    }
    file.close();
    

    Leider gibt das Programm dann nur viele Zeilen mit Speicheradressen aus. Ist vermutlich ganz logisch, aber ich weiß einfach noch nicht so genau wie man mit den fstreams um geht.

    Desweiteren wäre noch interessant ob es wirklich die bessere Wahl ist mit fstreams zu arbeiten, oder ob es andere Möglichkeiten gibt??

    lg und danke für eventuelle Infos
    Darian



  • Servus, ich bin mir jetzt auch nicht sicher ob das stimmt aber probiers mal anstatt
    cout mit file. Da du ja sagst das du mit (fstream::in) einlesen willst musst du file zum lesen hernehmen.

    fstream file;
    string zeile;

    file.open("heightmap.bmp", fstream::in | fstream::binary);

    while(getline(file, zeile))
    {
    file << getline(file, zeile) << endl; // Hier die Änderung
    }
    file.close();

    du kannst am Anfang gleich anstatt

    fstream file;
    file.open("heightmap.bmp", fstream::in|fstream::binary);

    so schreiben

    ifstream file;
    file.open("heightmap.bmp", fstream::binary);



  • std::ifstream file_stream("heightmap.bmp", std::ios::binary);
    
    if (!file_stream) { std::cerr << "FEHLER: Datei \"heightmap.bmp\" konnte nicht geöffnet werden!" << std::endl; return false; }
    

    ... so willst du die Datei öffnen 🙂 Und jetzt musst du dir mal das BMP-Format angucken.



  • Hallo Leute, danke für die Infos, bin schon am werkeln und mir auch das Bitmap Format genauer am ansehen.

    Na ja, ich würde dann ja das File in das selbe File rein speichern wenn ich es mit file << getline...usw weiter mache.

    Ich möchte es ja vorerst einmal gerne am Bildschirm ausgeben. (bekomme jedenfalls einige Fehler komische Fehler beim kompilieren)

    Wo ist der Unterschied ob ich jetzt fstream::in oder ios:in benutzte.

    Das std:: brauche ich nicht weil ich using namespace std benutze.

    Jedenfalls einmal danke für die Hilfe
    Darian



  • hmm guck dir mal die Vererbungstabelle hier an: http://www.cplusplus.com/reference/ dann such dir einfach mal das niedrigste Elemente aus, bei das Flag definiert ist.

    Das std:: brauche ich nicht weil ich using namespace std benutze.

    Hmm schon richtig. using namespace ist ja auch meiner Ansicht nach vollkommen fehl am platze ist. Ist ja pure Faulheit.

    Na ja, ich würde dann ja das File in das selbe File rein speichern wenn ich es mit file << getline...usw weiter mache.

    Was willst du uns sagen?

    Aja std::getline und das Flag std::ios::binary ... nicht so sonderlich sinnig, was meinst du?

    Aja einmal ausgeben was in der Datei steht?

    std::ifstream file_stream("heightmap.bmp");
    std::copy(std::istream_iterator<char>(file_stream), std::istream_iterator<char>(), std::back_inserter(std::cout));
    


  • Binärdaten solltest du nicht mit getline(...) lesen, da sie ja keine Zeilenumbruch-Zeichen enthalten.
    Dafür gibt es die Methode read(...).

    P.S. Für Textdateien sähe deine Einlese-Schleife so aus:

    while(getline(file, zeile))
    {
        cout << zeile << endl;
    }
    


  • Hmm schon richtig. using namespace ist ja auch meiner Ansicht nach vollkommen fehl am platze ist. Ist ja pure Faulheit.

    Na ja, soweit ich weiß hat es keine Nachteile, es wird nichts langsamer oder schlechter, darum ist da Faulheit ja auch nicht Fehl am Platz 🙂

    Na ja, ich würde dann ja das File in das selbe File rein speichern wenn ich es mit file << getline...usw weiter mache.

    Was willst du uns sagen?

    Gute Frage 🙂 Weil AJA meinte ich kann es mit file << getline(file, zeile) << endl; ausgeben, und das ist mir nicht klar. Weil so würde man es ja in file rein schreiben was getline ausgibt?

    Aja std::getline und das Flag std::ios::binary ... nicht so sonderlich sinnig, was meinst du?

    Ist möglich ja, ich weiß es nicht, ich dachte dabei weil es eine binary ist, schreiben wir das ios::binary dazu, und weil ich jede Zeile nach der Reihe ausgeben will, mit getline. (bei einem kleinen ToDo Listen Programm dass ich einmal geschrieben habe, hat es so funktioniert)

    Nur jetzt beim einlesen von den pixeldaten in einen zwei dimensionalen Array will es nicht gehen.

    Bezüglich

    std::copy(std::istream_iterator<char>(file_stream), std::istream_iterator<char>(), std::back_inserter(std::cout));
    

    Hm? Wieso mit copy ausgeben?
    Diese Zeile ist mir leider gar nicht klar.

    @th, ok, das mit read werde ich mir einmal ansehen...

    lg und danke für die Infos
    Darian



  • mit dem std::copy wollte devil nur mal wieder angeben, was er tolles weiß.
    aber eigentlich ist das ausgeben eines bildes als text sowieso quatsch.



  • Ja vermutlich, aber ich wollte es ja gar nicht ausgeben, ich will es grundsätzlich in einen zwei Dimensionalen Array speichern, damit ich es später dann zum weiterarbeiten benutzen kann. (Terran mit OpenGL aus Highmap)
    Brauche also nur die Pixelwerte die von 0-255 gehen müßten.

    lg Darian



  • aja ist klar ihr beiden ganz schlauen.
    @Hinweis:

    Darian schrieb:

    Ich möchte es ja vorerst einmal gerne am Bildschirm ausgeben. (bekomme jedenfalls einige Fehler komische Fehler beim kompilieren)

    ... ?
    @Darian:

    Hm? Wieso mit copy ausgeben?
    Diese Zeile ist mir leider gar nicht klar.

    Hmm ... es werden alle Zeichen der Datei in den Ausgabe-Stream std::cout kopiert ...

    Naja mal eure Sinnvollen & Geistreichen Bemerkungen (s. "hinweis") außer acht lassen. Hast du denn die Breite & Höhe der Heightmap? Ja, steht im BitmapHeader ... Wenn du dich folglich mit dem BMP-Format mal auseinander gesetzt hast, wirst du feststellen, das die Daten, die du haben willst, nicht direkt am Anfang der Datei stehen ... den Datenblock kannst du, wenn du es ganz primitiv machen willst, mit 2 verschachtelten for-Schleifen und der get-Funktion eines std::istreams realisieren.



  • der erste post von devil war gut, aber das mit std::copy zur ausgabe ist hier sinnlos, wie gesagt angeben...

    Und jetzt schau dir endlich mal das bmp format an und versuch es zu verstehen.



  • Hallo,

    ja das habe ich mir schon angeschaut, und bin demnach gerade dabei die Auflösung aus zu lesen.

    Damit wir einmal konkret werden, sende ich hier einfach mal den einfachen Code, bin wie ihr gemerkt habt noch neu auf dem Gebiet.

    #include <iostream>
    //#include <string>
    #include <fstream>
    
    using namespace std;
    
    int main ()
    {
      int length;
      char * buffer;
    
      ifstream heightmap;
      heightmap.open ("heightmap.bmp", ios::binary );
    
      if(!heightmap)
      {
    	cerr << "FEHLER: Datei \"heightmap.bmp\" konnte nicht geöffnet werden!" << endl;
    	return -1;
      }
    
      // get length of file:
      heightmap.seekg (0, ios::end);
      length = heightmap.tellg();
      heightmap.seekg (0, ios::beg);
    
      // allocate memory:
      buffer = new char [length];
    
      // read data as a block:
      heightmap.read (buffer,length);
      heightmap.close();
    
      cout.write (buffer,length);
      delete buffer;
    
      return 0;
    }
    

    Für die breite muß ich einfach 18 Byte nach vorne kommen, weiß noch nicht wie, und in lesbaren Zahlen das auslesen, das selbe für die anderen Informationen.

    Arbeite unter Linux, und bin wie gesagt noch Neuling bei dem ganzen.

    lg
    Darian



  • seekg zum vorschieben ... ehm und dann einfach my_file.read(reinterpret_cast<char*>(&my_integer), sizeof(int)); bsw. um einen Integer auszulesen.



  • Eigentlich habe ich schon einen fetten Text geantwortet, abe keine Ahnung wo der jetzt hin ist.

    Also heightmap.seekg (18, ios::beg); => zum 18 Byte nach vorne schieben (konnte ich jetzt noch nicht testen)

    Und das nächste ist mir nicht klar. sizeof(int). Int hat ja normalerweise 32 Byte, aber wenn ich "cout << sizeof(int);" schreibe, gibt es genau 4 aus...? (von dem her wäre es ok, weil die Breite laut Wiki mit 4 Bytes gespeichert ist)

    Und bitte noch um einer genauer Erklärung für das:
    reinterpret_cast<char*>(&length)

    Ist mir eher weniger, bis gar nicht klar 🙂

    lg
    Darian



  • Darian schrieb:

    Und das nächste ist mir nicht klar. sizeof(int). Int hat ja normalerweise 32 Byte, aber wenn ich "cout << sizeof(int);" schreibe, gibt es genau 4 aus...?

    Wenn dann 32 Bit

    Und bitte noch um einer genauer Erklärung für das:
    reinterpret_cast<char*>(&length)

    read will nen char* wo die daten hingeschrieben werden sollen. du nimmst die adresse wo dein length im speicher liegt und tust so, als ob diese 4 bytes, auf die die adresse, zeigt ein char* wären, indem du castest. ist aber ein bisschen gefährlich, weil int nicht immer 4 bytes sein müssen, aber auf den meisten 32 bit systemen sind es 4, auf 64 bit system sind es wahrscheinlich 8. also nimm lieber nen anderen datentyp der immer 4 byte groß ist.



  • Ah ja stimmt, das mit dem Bit und Byte habe ich da jetzt ein bisschen durcheinander gebracht.

    Das mit dem reinterpret_cast ist mir jetzt klar, ich Frage mich nur ob einfach so zu casten so eine gute Idee ist, ist es egal wenn man sowas macht?

    Ich kriege nur eine große negative Zahl zurück.

    #include <iostream>
    #include <fstream>
    
    using namespace std;
    
    int main ()
    {
    
    	char * buffer;
    	int breite;
    	int hoehe;
    
    	ifstream heightmap;
    
    	heightmap.open ("heightmap.bmp", ios::binary );
    
    	if(!heightmap)
    	{
    		cerr << "FEHLER: Datei \"heightmap.bmp\" konnte nicht geöffnet werden!" << endl;
    		return -1;
    	}
    
      //vorschieben zum breiten Bereich
    	heightmap.seekg (18, ios::beg);
    
    	//Auslesen und schliessen aus dem Str
      heightmap.read(reinterpret_cast<char*>(breite), sizeof(int));
      heightmap.close();
    
    	//Ausgabe der Breite
    	cout << breite << endl;
    
    	return 0;
    }
    

    Was stimmt da jetzt wieder nicht, bitte um konkrete Infos, wäre super wenn mir da verständlich jemand weiter helfen könnte.

    lg Darian



  • Du mußt den Zeiger auf die int-Variable casten und nicht die Variable selbst.

    heightmap.read(reinterpret_cast<char*>(&breite), sizeof(breite));
    


  • Mah stimmt, so ist es richtig, jetzt hat es funktioniert, und sogar die richtige Breite wurde ausgegeben.

    Nachdem das jetzt passt, kann ich mal gemütlich versuchen das alles dementsprechend zu verarbeiten. Jetzt wo ich die Basics habe.

    lg und danke für diesen Tipp, habe ich wohl übersehen
    Darian



  • Habe jetzt einmal den Header eingelesen, und stehe jetzt bei dem auslesen der ersten Pixel, da scheint es irgendwie wieder weniger zusammen zu passen.

    Muß ich jetzt ersteinmal die Farbpalette in einen Array laden?

    Hier er Code:
    http://nopaste.info/94d173b2b5.html

    Wäre super wenn ich noch ein paar Infos kriege.
    Ach ja, hätte ich den Header auch irgendwie mit einer Schleife laden können, anstatt alles manuell aus zu schreiben?? (mir ist da irgendwie nichts eingefallen!)

    lg
    Darian



  • Darian schrieb:

    Habe jetzt einmal den Header eingelesen, und stehe jetzt bei dem auslesen der ersten Pixel, da scheint es irgendwie wieder weniger zusammen zu passen.

    Muß ich jetzt ersteinmal die Farbpalette in einen Array laden?

    Wenn das Bild eine Farbepalette hat, vermutlich ja. Andernfalls kann es sein, daß zwischen Header und Bilddaten noch Müll steht - im Header steht auch drin, wo die Nutzdaten beginnen.


Anmelden zum Antworten