failbit bei fstream/schleife verhindern



  • Ich mache bei einem Lesedateizugriff eine Schleife um die gesamte Datei einzulesen.

    std::string data;
    char x;
    while(in.get(x)) { data += x; }
    

    Das ganze Habe ich natürlich über try/catch abgesichert. Jetzt ist es natürlich so , dass das failbit gesetzt wird bei z.B. einem falschen dateinamen und am ende der schleife...

    Wie verhindere ich jetzt das failbit bei der schleife?
    Klar es gibt die funktion dieses bit zu löschen, aber sofort beim ende der datei tritt natürlich catch ein.

    Ich habe gelesen es könnte über iteratoren funktionieren, wobei ich nicht weiß wie diese funktionieren...



  • Ich möchte nur auf den falschen dateinamen reagieren...



  • ifstream ifs(name);
    if (!ifs.is_open()){ cout << ":("; }
    


  • danke aber das prüft nur ob die datei noch offen ist. Ich möchte das die schleife auf das ende der datei testet



  • Okay herausgefunden

    fstream in(name);
    in.seekg(0, std::ios_base::end);
    int length = in.tellg();
    in.seekg(0, std::ios_base::beg);
    while(in.tellg() != length) {}
    


  • chris01349 schrieb:

    Okay herausgefunden

    fstream in(name);
    in.seekg(0, std::ios_base::end);
    int length = in.tellg();
    in.seekg(0, std::ios_base::beg);
    while(in.tellg() != length) {}
    

    Nö, nicht herausgefunden.
    Mach Deine alte Schaleife in klassenmethodes if rein.



  • habs ausprobiert. wenn ich das mach wie vorgeschlagen springt mir catch sofort in die failbit-fehlermeldung.



  • Das scheint ein Paradebeispiel für eine schlecht gestellte Frage zu sein: es werden drei Zeilen nichtssagender Code präsentiert und die entscheidenden Dinge stehen höchstens im Nebensatz. Dass dann die Antworten unbefriedigend sind, ist nur logisch.

    Du scheinst in dem Stream Exceptions aktiviert zu haben, sagst aber nicht, welche Bitmask du verwendest. Dann erwartest du, dass die Exceptions in einer bestimmten Art und Weise geworfen werden, sagst aber nicht genau, wie. So wirst du dein Problem wohl nicht lösen.



  • ich teste einen ifstream auf failbit und badbit
    und das failbit, wird aktiviert sobald die schleife außerhalb der datei ist...

    Meine Frage war nun wie löse ich es ohne das das failbit in der schleife ausgelöst wird, da ich das failbit nur auslösen möchte bei falschem dateinamen z.B.

    eof() testet auf außerhalb der datei also fällt das schonmal raus
    in.get(x) genauso weil das ausgeführt wird solang der positionszeiger innerhalb der datei ist springt aber auch raus beim dateiende...

    mit

    fstream in(name);
    in.seekg(0, std::ios_base::end);
    int length = in.tellg();
    in.seekg(0, std::ios_base::beg);
    while(in.tellg() != length) {}
    

    funktioniert was ich vorhab, da die schleife nur bis zum letzten zeichen geht.

    Welche möglichkeiten gäbe es sonst noch?



  • chris01349 schrieb:

    ich teste einen ifstream auf failbit und badbit

    Nicht im gezeigten Code.

    Meine Frage war nun wie löse ich es ohne das das failbit in der schleife ausgelöst wird, da ich das failbit nur auslösen möchte bei falschem dateinamen z.B.

    Warum?



  • chris01349 schrieb:

    aber sofort beim ende der datei tritt natürlich catch ein.

    Welches catch? Nichts im gezeigten Code läßt einen Exceptions erwarten.



  • std::string file::read(std::string title) {
     std::ifstream in;
     char x; std::string data;
     int length = this->length(title);
    
     try {
      in.exceptions(std::ios::badbit|std::ios::failbit);       in.open(title.c_str(),std::ios::binary|std::ios::in);
      while(in.tellg() != length) { 
      in.get(x);
      data += x;
       } 
      in.close();
     }
    
     catch(std::ios::failure&) {
     if(in.bad()) { return("0"); } 
     if(in.fail()) { return("0"); } }
     return(data);
    }
    

    //length() gibt die zeichenlänge zurück

    So sieht der eigentlich code aus. Wenn ich jetzt aber am Ende der Schleife bin tritt natürlich in.fail() auf und der Dateninhalt wird mir nicht zurückgegeben. So wird aber glaub ich auch auf den falschen dateinamen geprüft. So wie der Code jetzt ist konnte ich es lösen, aber gibt es eine elegantere methode?

    Und ich habe eine methode check() die genau auf den dateinamen prüft. Möchte es aber nicht so viel verschachteln



  • Ich könnte natürlich failbit komplett herausnehmen, was ich aber vermeiden möchte



  • chris01349 schrieb:

    Ich könnte natürlich failbit komplett herausnehmen, was ich aber vermeiden möchte

    Warum? Du hast doch innen schon das while. Machst außen das if und brauchst .exceptions() nicht mehr, oder?



  • Nochmal leute wenn die schleife zu ende ist löst das eofbit automatisch das failbit aus, obwohl das gar nicht gesetzt ist... lass ich das failbit weg prüft dieses bit nicht mehr ob die datei vorhanden ist... ich kann damit leben aber ist das richtig so? oder was kann man da machen?



  • mein neuer code:

    bool file::copy(std::string input,std::string output) {
     std::ifstream in; std::ofstream out;
    
     try {
      in.exceptions(std::ios::badbit|std::ios::failbit);
      out.exceptions(std::ios::badbit|std::ios::failbit);
      in.open(input.c_str(),std::ios::binary|std::ios::in);
      out.open(output.c_str(),std::ios::binary|std::ios::out);
      char x; while(in.get(x)) { out.put(x); }
      in.close(); out.close();
     }
    
     catch(std::ios::failure&) {
      if(in.bad())   { return 0; }
      if(in.fail())  { return 0; }
      if(out.bad())  { return 0; }
      if(out.fail()) { return 0; }
     } return 1;
    
    }
    

    probiert es einfach mal selbst aus... und lasst dann mal das failbit von in. weg dann funktionierts

    ich weiß unschön vom stil...



  • Ich sehe nicht, warum du Exceptions wirfst bei eofbit, failbit oder
    badbit. Die unterschiedlichen Bit Masken sind doch dazu da um unterschiedliche Zustände zu händeln. Wenn du die alle gleich behandelst wirfst du den Vorteil weg.

    ifstream in(name);
    std::string data;
    if (in.is_open()){
      char x;
      while(in.get(x)) //iteriert bis EOF
        data += x; 
    }
    else{
    ...
    }
    

    //Edit: Natürlich kannst du nach der while Schleife den Zustand deines Streams überprüfen um zu testen weshalb das Lesen abgebrochen wurde, falls das für dich interessant ist.



  • bool file::copy(std::string input,std::string output) {
     std::ifstream in; std::ofstream out;
     in.exceptions(std::ios::badbit|std::ios::failbit);
     out.exceptions(std::ios::badbit|std::ios::failbit);
    
     try {
      in.open(input.c_str(),std::ios::binary|std::ios::in|std::ios::out);
      out.open(output.c_str(),std::ios::binary|std::ios::out);
      in.seekg(0,std::ios::end); long int x = in.tellg(); in.seekg(0,std::ios::beg); char z;
      for(int y = 0;y < x;y++) { in.get(z); out.put(z); }
      in.close(); out.close();
     }
    
     catch(std::ios::failure&) {
      if(in.bad())   { return 0; }
      if(in.fail())  { return 0; }
      if(out.bad())  { return 0; }
      if(out.fail()) { return 0; }
     } return 1;
    
    }
    

    gelöst: so wird kein eof ausgelöst und nicht existierende dateien werden einfach erstellt...
    und die exception greifen trotzdem einwandfrei...

    es ist nicht lesbar geschrieben ich weiß...


  • Mod

    War es wirklich nötig, diesen 14 Monate alten Thread wieder zu erwecken?



  • google 1. treffer:

    http://stackoverflow.com/questions/10195343/copy-a-file-in-a-sane-safe-and-efficient-way

    von deinem code würde ich aus mehreren gründen abraten.
    ich bin mir auch ziemlich sicher, dass dieser nicht ohne warnings compiliert. (int / long vergleich in deiner schleife)

    catch(std::ios::failure&) {
      if(in.bad())   { return 0; }
      if(in.fail())  { return 0; }
      if(out.bad())  { return 0; }
      if(out.fail()) { return 0; }
     }
    return 1;
    

    ->

    catch(const std::ios::failure&)
    {
      return false;
    }
    return true;
    

    wenn dir aber exceptions ohnehin bekannt sind, wieso dann nicht einfach die exception weiterwerfen und die signatur deiner fkt zu void f(string,string) ändern.


Anmelden zum Antworten