Input/Output mit FileDialog Verzeichnis wechseln

nossek

Aktives Mitglied
Guten Morgen,

Wenn man wie folgt eine Datei schreibt:, wird die Datei in das "aktuelle Verzeichnis" geschrieben (das ist in meinem Fall der Ordner des NetBeans Projektes, in dem das main-projekt liegt):
Java:
public void saveAs(String filename){
        try{
            File f = new File(filename);
            FileOutputStream fos = new FileOutputStream(f);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(this);
            fos.close();
            this.unsavedChanges = false;
        }
        catch(Exception e){
            System.out.println("Speichern hat nicht geklappt!");
            e.printStackTrace();
        }
    }


Ich möchte zum speichern einen FileDialog verwenden. Leider nur will es mir nicht gelingen, in das das per FileDialog ausgewählte Verzeichnis zu schreiben.

Das scheint eine sehr einfache Frage zu sein, habe aber leider nichts für mich verständiches gefunden. Dachte es müßte eine Methode System.setDirectory(String) oder oos.setDirectory(String) geben, gibt es aber nicht...
 
Zuletzt bearbeitet:
Öhm, warum nicht
Code:
pfad+dateiname
? (bzw.
Code:
pfad+separator+dateiname
, bin mir da jetzt nicht sicher wie es zurückgeliefert wird)
 
Das scheint eine sehr einfache Frage zu sein, habe aber leider nichts für mich verständiches gefunden. Dachte es müßte eine Methode System.setDirectory(String) oder oos.setDirectory(String) geben, gibt es aber nicht...

???:L

Du musst lediglich die Informationen aus dem FileDialog ziehen (wie schon gesagt wurde pfad + filename), diese zusammensetzen, ein neues File erzeugen mit zB
Code:
new File(path+filename)
und dieses dann wie du es schon gemacht hast per OutputStream schreiben.
 
Ja, das funktoniert:
Java:
FileDialog dialog = new FileDialog(mainFrame, "Save as", FileDialog.SAVE);
                dialog.setVisible(true);
                String filename = dialog.getFile();

                if (filename != null) {
                    file.saveAs(dialog.getDirectory()+filename);
                }
                dialog.dispose();
                }
Man sollte wohl noch prüfen, ob das Verzeichnis bereits ein File dieses Namens enthält und abfragen, ob es überschrieben werden soll, nicht wahr?

Vielen Dank jedenfalls für die mal wieder blitzschnellen und hilfreichen Antworten!
 
Zuletzt bearbeitet:
Man sollte wohl noch prüfen, ob das Verzeichnis bereits ein File dieses Namens enthält und abfragen, ob es überschrieben werden soll, nicht wahr?

Ja, aber evtl macht das der Dialog schon für dich, das solltest du mal abchecken. Außerdem solltest du für den Fall, dass der Ordner, in den gespeichert werden soll, noch nicht existiert, schauen was passiert. Eventuell musst du ein
Code:
file.mkdirs()
vorher aufrufen.
 
Ja, der FileDialog warnt, wenn man eine vorhandene Datei überschreiben will, prima.

Außerdem solltest du für den Fall, dass der Ordner, in den gespeichert werden soll, noch nicht existiert, schauen was passiert. Eventuell musst du ein file.mkdirs() vorher aufrufen.

Ich kann per FileDialog doch nur existierende Ordner auswählen. Oder mit dem Button "Neuer Ordner" einen neuen Ordner erzeugen. Unter welchen Bedingungen könnte das von Dir beschriebene Problem auftreten?
 
Ich kann per FileDialog doch nur existierende Ordner auswählen. Oder mit dem Button "Neuer Ordner" einen neuen Ordner erzeugen. Unter welchen Bedingungen könnte das von Dir beschriebene Problem auftreten?

Naja du kannst als User ja den Filename eingeben. Gibt man sowas wie "test/myFile.txt" ein, dann wird das wohl als Pfad interpretiert. Würds auf jeden Fall mal testen. Auch wenns nicht so wahrscheinlich ist, dass sowas passiert, aber falls es passiert bist du drauf vorbereitet. 😉 Vielleicht wird der Ordner aber auch schon beim Schreiben der Datei automatisch erstellt, das weiß ich nicht.
 
wenn man als Dateinamen "test/myFile.txt" eingibt, wird seltsamerweise eine Datei dieses Namens erzeugt. Da es in meinem Programm derzeit noch andere Probleme beim speichern gibt kann ich noch nicht testen ob man eine Datei die einen Seperator enthält auch öffnen kann...

(ist es wohl denkbar dass das Verhalten in solchen Situationen Betriebssystemabhängig ist? Ich arbeite unter OS X)
 
wenn man als Dateinamen "test/myFile.txt" eingibt, wird seltsamerweise eine Datei dieses Namens erzeugt.

:shock:

(ist es wohl denkbar dass das Verhalten in solchen Situationen Betriebssystemabhängig ist? Ich arbeite unter OS X)

Weiß nicht wie das auf einem Mac läuft, aber unter Windows kannst du erst garnicht einen / in den Dateinamen eingeben. Deswegen dachte ich, dass er da evtl "automatisch" einen Pfad draus macht. Aber ja, ist wohl abhängig vom Betriebssystem.

Da es in meinem Programm derzeit noch andere Probleme beim speichern gibt kann ich noch nicht testen ob man eine Datei die einen Seperator enthält auch öffnen kann...

Da bin ich mal gespannt. Da ers aber anscheinend schon gespeichert hat.. komisch.
 
Ich hänge fest.

meine Klasse CardFile hat folgende Methode:
Java:
public static CardFile loadFromFile(String filename){
        try {
            FileInputStream fis = new FileInputStream(filename);
            ObjectInputStream ois = new ObjectInputStream(fis);

            CardFile kartei = (CardFile) ois.readObject();
            ois.close();
            return kartei;
        }
        catch (Exception e) {
            System.out.println("Laden hat nicht geklappt!");
            e.printStackTrace();
            return null;
        }
    }

und die funktioniert soweit, wenn ich den Namen einer existierenden Datei im aktuellen Verzeichnis als Argument übergebe. Sie funktionert auch, wenn ich den Pfad/Dateinamen einer existierenden und passenden Datei übergebe.

Das Hauptfenster MainFrame hat ein Menü, wobei der ActionListener des Menüpunktes "Open" folgendermaßen aussieht;
Java:
openAction.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                FileDialog dialog = new FileDialog(frame, "Open", FileDialog.LOAD);
                dialog.setVisible(true);
                String filename = dialog.getFile();
                if (filename != null) {
                    file = CardFile.loadFromFile(dialog.getDirectory()+filename);
                }
                dialog.dispose();
                }
            });
frame = Instanzvariable von MainFrame, ein JFrame.
file = Referenz auf ein CardFile-Objekt.

Das laden funktioniert nicht, es wird aber auch keine Exception geworfen. file ist nach der Aktion unverändert. Die Aktion findet aber statt, das habe ich geprüft.
???:L
Wo liegt der Fehler???
 
Gib dir doch aus, was du da als Parameter übergibst.

habe ich schon probiert. Der Pfad/Dateiname, der innerhalb des Actionlisteners an loadFromFile übergeben wird ist korrekt.

Habe auch probiert, im Konstruktor von MainFrame file per loadFromFile mit genau diesem Pfad/Dateinamen zu initialisieren. In dem Fall wird die entsprechende Datei dann korrekt geladen. :bahnhof:
 
Zuletzt bearbeitet:
Habe den Fehler gefunden. Es war ein Problem von meinem EditPanel (Karten erzeugen, löschen, editieren). Der Konstruktor vom EditPanel hatte als argument ein CardFile "file". Da hatte die IDE gemeckert:"local variable is accessed from within inner class" - und zwar bei den ActionListenern, die methoden von file aufrufen. Da habe ich den Vorschlag der IDE umgesetzt "make file final" - das war wohl nicht so schlau, der Konstruktor sah dann so aus:
Java:
public EditPanel(final CardFile file){
    ....
}

Das hat offenbar dazu geführt, daß die Instanzvariable "file" vom EditPanel nach dem Aufruf von file = loadFromFile() im MainFrame weiterhin das file referenziert, das im Konstruktor von EditPanel übergeben wurde.

Jetzt habe ich den Konstruktor dahingehend geändert, daß er kein Argument hat. Und dem EditPanel eine methode setFile(CardFile file) eingebaut, die nach jedem laden bzw. neu anlegen eines CardFiles aufgerufen werden muß. Das funktionert. Hat aber den Schönheitsfehler, daß der Konstruktor kein vollständiges Objekt zurückgibt. Gibt es eine bessere Alternative? z.B. den Konstruktor von EditPanel mit Argument "static FileCard" belassen nach jedem Laden im MainFrame
Java:
editpanel = new EditPanel(file)
ausführen?

Zu der Frage, die sich gestern ergeben hat:
Ja, man kann beim speichern einen Dateinamen wie "test/myFile" eingeben, und es wird eine Datei dises Namens erzeugt und die kann auch per loadFromFile ganz normal geladen werden.

Das ist sehr sehr seltsam, aber ist das schlimm? Man könnte das abfangen, indem man unterbindet, daß Dateinamen Seperatoren enthalten.
 
Zuletzt bearbeitet:
wenn man als Dateinamen "test/myFile.txt" eingibt, wird seltsamerweise eine Datei dieses Namens erzeugt.
:shock:
Das ist mir mal mit einem Doppelpunkt im Dateinamen passiert. Die Datei wurde normal gespeichert, aber der Name dann nur bis zum Doppelpunkt angezeigt. Diese Datei konnte ich nicht mehr löschen, da mir Windows Vista sagte, dass die Datei nicht gefunden werden konnte. Auch der Parent-Ordner konnte deswegen nicht gelöscht werden. Eine Formatierung hat dann aber geholfen. 😀
 
Auch nicht besser. Was meinst du denn mit "kein vollständiges Objekt"?
ist es denn falsch zu sagen daß "ein Konstruktor Objekte erzeugt"?

mit "unvollständiges Objekt" meine ich folgendes:
Objekte der Klasse EditPanel sind dafür da, Objekte der Klasse CardFile anzuzeigen und zu bearbeiten.
Also ergibt ein EditPanel Objekt keinen Sinn, dessen Instanzvariable file (die auf ein CardFile-Objekt verweist) nicht initialisiert ist. = Unvollständiges Objekt.

Ich kenne mich ja (wie man merkt) nicht aus, aber es gibt doch viele Klassen, die keinen Konstruktor ohne Argumente haben, z.B. Scanner. Habe das bislang so verstanden, das es bei solche Klassen für die Instanzvariablen, die man auf jedem Fall im Konstruktor per Argument setzen muß keine sinnvollen Default-Werte gibt. Eben um das, was ich "unvollständig" nenne zu verhindern.

Klar, man könnte in meinem Fall auch im Konstruktor file erstmal mit file = new CardFile() initialisieren. (ergibt aber auch nicht wirklich Sinn. EditPanel soll auf vorhandenen CardFiles arbeiten!)
Ich finde es unschön, daß man, selbst wenn man beim Konstruktoraufruf schon weiß, welches CardFile dargestellt werden soll file nicht gleich im Konstruktor entsprechend setzen kann?!

Falls das alles Blödsinn ist bin ich natürlich dankbar für Belehrungen!

xehpuk hat gesagt.:
Das ist mir mal mit einem Doppelpunkt im Dateinamen passiert.
Unter OSX sind Doppelpunkte im Dateinnamen nicht erlaubt - ein ":" wird im Filedialog automatisch in ein "-" umgewandelt.
Habe nochmals eine Datei mit dem Namen xxx/yyy gespeichert. Wie gesagt, die Datei wird korrekt mit diesem Namen gespeichert. Und man kann sie im Filedialog auch auswählen und öffnen. Habe mal den String, der an loadFromFile übergeben wird in der Konsole ausgegeben, da steht dann allerdings "xxx:yyy".
 
Zuletzt bearbeitet:

Zurück
Oben