Laufzeit-Fehler: Programm kann DAtei nicht zum lesen öffnen



  • Hi leutz,

    ich hab n kleines Problem mit einem von mir aufgesetzten Code. Und zwar wollte ich mir ein (erstmal minimalistisches) Programm schreiben, um meine Finanzen zumindest mit einem kleinen Ausgabe- und Einnahmen-Protokoll und dem aktuellem Guthaben was ich im Portmonai habe, zu verwallten. Da ich noch schüler bin ist das mit dem Portmonai übrigens wörtlich zu nehmen 😉

    Da ich den Code zwar windows entwickel, aber in später auch auf linux portätieren will, habe ich mir überlegt, das Protokoll und die aktuellen Guthabenszahlen in einer stinknormalen ASCII-Datei zu speichern. Und genau da fangen die Schwierigkeit an... Ich hab noch nicht viel mehr als das öffnen der Datei zum lesen, und schon kommen die probleme. Compilieren lässt sich das ganze anstandtslos, aber guckt euch einfach mal folgenden Code an:

    // main.cpp
    
    #include <cstdlib>
    #include <iostream>
    #include "daten.h"
    
    using namespace std;
    
    int main(int argc, char *argv[])
    {
    daten konto; // erzeuge Instanz der Klasse Daten
    konto.lesen(); // rufe methode "lesen" aus klasse "daten" zum lesen der datei auf
    }
    
    // daten.cpp
    
    #include <iostream>
    #include <fstream>
    #include "daten.h" // include klassen-deklaration
    
    using namespace std;
    
    int daten::lesen(void) // deffinition der Funktion 
    {
    ifstream datei; // instanz der klasse ifstream erzeugen
    datei.open("daten.fnz", ios_base::in); // datei "daten.fnz" im lesemodus öffnen
    
    if(!datei) // wenn "daten.fnz" nicht geöffnet werden konnte, dann
    cout << "Datei kann nicht geoffnet werden!"; // Fehler ausgeben und programm abbrechen
    
    else // nur ausführen, wenn datei geöffnet werden konnte!
        {
    char zeichen;
    while(!datei.eof()) // so lange ausführen, bis ende der datei erreicht
                       {
    zeichen = datei.get(); // nächstes zeichen einlesen
    cout << zeichen; // zeichen ausgeben
                       }
        }
    datei.close(); // datei schließen
    
    }
    
    // daten.h
    
    #ifndef daten_h
    
    using namespace std;
    
    class daten
    {
    private:
            int schulden;
    
    public:
           int lesen(void);
    };
    
    #endif
    

    zum code:

    Ich hab vor ner halben ewigkeit schonmal mit dateien und C++ programmiert, davon habe ich auch noch den Source des damals funktionierenden Beispiels - nur leider auf diskette und mein neuer Rechner hat kein Floppy-Drive mehr 😞

    Erstmal soll das Programm den Inhalt der Datei nur lesen und ausgeben, in der datei steht jediglich PHAJHGSDZ oder so 😉 iss ja bisher nur das grundgerüst, wenn das bearbeiten der datei funktioniert mahce ich was sinnvolleres draus ^^

    die datei liegt im selben verzeichnis wie das programm nach dem compilen und linken, sie hat genau den namen (die endung .fnz soll übrigens für "finanzen" stehen ^^) wie es das Programm von mir eingetrichtert bekommen hat, sie ist nicht schreibgeschützt, und dennoch scheitert es immer an einem "datei kann nicht geoeffnet werden!" auf der console.. wenn ich diese überprüfung wegmache verfängt er sich nach dem aufruf in der win32-colsole sofort inner endlosschleife, was ich nur dadurch beendet bekomme, die console wegzuklicken...

    kann mir einer sagen, was in diesem gott verdamten source ich falsch gemacht habe? 😉

    danke im vorraus:
    Jan-David

    P.S.:
    Das das ganze übrigens OOP ist, wo hier bei sowas prozedual auch gereicht hätte, liegt daran, dass ich zwar das programm am ende auch brauchen kann, aber gleichzeitig den umngang mit klasen nochmal üben wollte, da ich hier bisher mehr theoretisches wissen aber kaum praxis erfahrung habe... War ganz erstaunt dass die klasse an sich keine probleme gemacht hat 😉



  • Klappt es denn, wenn du den Dateinamen mit absolutem Pfad angibst?

    Btw, zwei Punkte zu deinem Header:
    * "using namespace std" ist in Headern nicht zu empfehlen - und in deinem Fall auch überflüssig.
    * zu einem kompletten Include-Guard gehört noch ein "#define daten_h" hinter dem "#ifndef daten_h"



  • hehe ^^, zu dem header: das war flüchtigkeitsfehler ^^ normaler weise deifniere ich den schalter auch, wenn ich ihn schon abfrage, sonnst hätte das prinziep der bedingten compilierung ja keinen sinn ^^

    und, ich glaub es kaum, es GEHT mit absolutem pfad!!!

    LoL hätte ich auch drauf kommen können ^^ ich wunder mich halt nur, da ich ja schonmal sowas gemacht hab, und das hab ich unter win XP laufen lassen, und da war es KEIN problem mit relativem pfad ^^ naja, ich hab eh probleme, teilweise... ich hab das programm auf D:\ liegen, win liegt aber auf C:\ und ich kann in der console auch mittels cd nicht ins ein verzeichnis auf D:ß wechseln... könnte es daran liegen? ICh muss gleich los zur schule, ich versuche dananch mal, was ist, wenn ich das ganze auf C:ß lege, ob es dann mit relativem pfad geht!

    danke übrigens für die schnelle hilfe, ich hab gedacht so früh morgens isnd alle in der schule oder im büro 😉

    dann verbessere nach der schule noch den cpompiler-schalter und werd dann heute nachmitag noch weiter an dem eigentlichen ausbau des proggies basteln ^^

    verrückt, dass es daran scheiterte ^^ ich konnte auf brech und verderb keinen fehler finden ^^

    gruß:
    jd-fun



  • Laufwerke wechselt man auch nicht mit "cd" 🙂 Gib einfach mal in der DOS-Konsole "D:" ein, dann müsstest du eigentlich auf dem richtigen Laufwerk landen.



  • jo, damit geht es, ich kann nach D:\ wechseln ^^
    aber warum geht es nich mit dem relativen pfad? Wie gesagt, ich hatte des schonmal, hatte den vorteil dass man es auch auf anderen rechnern verwenden konnte ^^ und nu muss ich immer nen neuen pfad eincomiplen wenn n anderer hinsoll ^^ doll ^^ naja, ma gucken, vielleicht bastel ich sowas ähnliches wie in der pre-install für apt unter linux, dass man eingeben kann wo was liegt was das programm braucht ^^

    gruß:
    jd-fun



  • Also mal ein paar Anmerkungen von mir zu deinem Programm:

    1. relative Pfade funktionieren unter Windows und Linux (auch mit deinem Code), allerdings sollten die Daten immer in einem Unterverzeichnis von deiner exe liegen.

    2. Da du das ganze mal nach Linux portieren willst und mit der Dateiendung .fnz signalisierst das sowieso niemand außer deinem Programm da ran so. Würde ich das ganze mit Binärdatein machen, nur so kannst du die Datein dann von Linux nach Windows tauschen und umgekehrt. Unter Linux ist der Zeilenumbruch nämlich anders als unter Windows. Das ganze hätte auch den Vorteil, dass du dir das parsen der Datei sparen kannst und die Variabeln deiner Klasse direkt in die Datei kloppen kannst.

    3. Beachte bei relativen Pfaden immer, das wenn der Nutzer eine Verknüpfung zu deinem Programm anlegt und das Arbeitsverzeichnis ändert, die ganzen relativen Pfade nicht mehr stimmen (das kann man aber normalerweise vernachlässigen, du kriegst es unabhängig davon IMHO nur mit Betriebssytem abhängigen Funktionen hin)

    4. Ich benutze für die Abfrage immer datei.is_open(), ist aber glaube ich eher Geschmacksache



  • wie gesagt: relative haben eben _nicht_ gefunzt, sonns wäre dieser thread hier gar nicht erst entstanden... und ich sehe eher bei absoluten angaben das problem, dass der user mit dem ändern des verzeichnisses alles schrott machen kann ^^ denn dann weißt der absolute pfad ja ins leere... bei relativem pfad stimmt es im neuen verzeichniss wieder, wenn der user ALLEs kopiert... wenn er eh die hälfte da lässt wo es war geht eh nix mehr, egal ob relativ oder absolute ^^ jo, ich wollte die datei auch noch in nen unterordner tun, aber iss ja erstmal nur nen grundgerüst zum testen ^^

    zum thema binär:
    würde ich gerne machen, aber ich habe noch keine erfahrung damit... ich kann mit textdateien umgehen, binär muss ich mir noch aneignen...

    ich frage mich ja die ganze zeit, warum relative angaben nich gehen, ich hatte, nun zum dritten mal erwähnt ^^, ja schonma n proggie und damit gings... komisch... hab ich damals andere confi einstellungen unter win gehabt? gibts da was was des beeinflussen könnte?

    du kriegst es unabhängig davon IMHO nur mit Betriebssytem abhängigen Funktionen hin

    bezieht sich das auf verknüpfungen oder auf relative pfadangaben? wenn letzteres würden alle bücher dazu lügen (fast alle exampel = relative pfade) und viele tuts im inet würden nix taugen... zumal es ja mal bei mir mit reinem C++ in der konsole ging...

    ich weiß ich klinge wahrscheinlich wie n n00b, bin ich eigentlich nich, nur mich verwirrt das gerade ein bissle 🙂

    danke nochmal für die hilfe ^^ noch danbarer wäre ich aber, wenn jemand mir sagen könnte warum es nich mit relativem pfad geht verdammt ^^ naja, ich glaub ich mach dazu bei gelegenheit nen neuen thread auf, hier weicht es vom thema ab, denn die frage iss ja beantwortet...

    gruß:
    jd-fun



  • Beispiel:

    ---- Ordner xy
    -- |
    -- |- test.exe
    -- |- test.txt

    Bei dieser Konstellation kannst du von test.exe aus auf test.txt zugreifen:

    fstream datei;
    datei.open("test.txt", ios_base::in);
    ...
    

    Wenn das bei dir nicht geht, ist das sehr seltsam. Ich mache das öfters und es funzt. Die einzige Möglichkeit die mir einfällt ist, das es nicht geht ist:

    1. Du erstellst z.B auf dem Desktop die Verknüpfung xy auf test.exe
    2. Du machst einen Rechtsklick auf die Verknüpfung/klickst auf Eigenschaften
    3. Tippst dann unter Arbeitsverzeichnis einen neuen Pfad ein.

    In diesem Fall bezieht sich das datei.open("test.txt"...), auf die test.txt im Arbeitsverzeichnis. (Das jemmand das ändert ist eher die Ausnahme)
    Standardmässig ist das Arbeitsverzeichnis (edit: heißt unter WindowsXP Ausführen in:), das Verzeichnis in dem die .exe liegt, die ausgeführt wird.

    Was ist denn mit dem schreiben von Datein? Funktioniert das mit relativen Pfaden?

    (Dummes edit: Gibts die zu lesende Datei überhaupt????)



  • Das Problem bei relativen Pfaden ist immer der Bezugspunkt. Und DOS verwendet dafür afaik die Position, an der du dich gerade befindest. Also solltest du besser erst in das Verzeichnis deiner EXE-Datei wechseln und dann das Programm starten.



  • omfg! Warum bin ich knaller da nicht selber drauff gekommen? Hab nochmal in nen relativen pfad "verwandelt" und hab in der console dann das verzeichnis gewechselt in das verzeichnis mit der exe! Siehe da: Es geht!

    dann ist es auchklar, warum bei dem anderen prog ging:
    ich hab die exe damals immer mit nem doppelklick gestartet, und damit die console geöffnet -> Damit war das verzeichnis in den sich das ganze auf der console abspielte natürlich festgesetzt, ohne dassich es gemerkt habe 🙂

    danke für die hilfe!
    jetzt ist mir klar, das relativ unter windows nicht relativ zur exe, sondern zum aktuelllen verzeichnis der dos-box ist!

    gruß:
    jd-fun


Anmelden zum Antworten