String kann nicht zu Pfad konvertiert werden

kodela

Bekanntes Mitglied
Hallo,

vor langer Zeit habe ich ein Klasse geschrieben, die über einen FileReader per BufferedReader eine Textdatei zeilenweise einliest. Danach wird Zeile für Zeile ausgewertet. Tritt in einer Zeile eine besondere Situation ein, wird sie mit entsprechenden Infos an eine vor der Auswertung bereits per FileWriter und BufferedWriter erstellte Textdatei ausgegeben. Dies funktioniert bestens.

Nun kam ich auf den Einfall, die erstellte Datei in den Fällen, in denen die mit dem FileWriter erstellte Datei ohne Eintrag bleibt, nach der Auswertung aller eingelesenen Zeilen zu löschen. Das will mir nun nicht gelingen, irgendwie stehe ich auf dem Schlauch. Dazu hier der Code, bei dem das Problem auftritt:

Java:
if (!eintrag) {
  Path tempFile = Files.createTempFile(
             aktPfad.substring(0, aktPfad.lastIndexOf("\\")+1) + "bug.txt");
  Files.delete(tempFile);
}

Der Debugger von NetBeans meldet mir:
Fehler: inkompatibler Typ - String kann nicht zu Pfad konvertiert werden
obwohl laut Debugger für
Code:
aktPfad.substring(0, aktPfad.lastIndexOf("\\")+1) + "bug.txt"
folgender String gebildet wird:
Code:
(java.lang.String) "D:\test\bug.txt"

Dies ist korrekt der genaue Pfad, in dem diese Datei erzeugt wurde.

Die hier genannten Bezeichner sind vereinfacht. entsprechen jedoch zu 100% dem tatsächlichen Code.

Warum ist die Konvertierung zu einem Pfad nicht möglich?

Gruß, kodela
 
Die Meldung kommt so wie Du die angegeben hast? Das wäre extrem lustig, da dort die Klasse auch übersetzt worden wäre.

Der Fehler besagt, dass Du einen String an einer Stelle angegeben hast, in der ein Path erwartet wird.

Aber generell frage ich mich, was Du da genau aufrufen willst. Files.createTempFile gibt es nur zwei Methoden, die alle mehr als ein Parameter benötigen. Das kann also so nicht übersetzen.

Bei so Problemen rate ich immer dazu, einfach einmal die Dokumentation anzusehen - also in dem Fall wäre das jetzt
 
Mit substring wirst du sicherlich nur den Path String ohne Slash bekommen.
Wenn du mit + "bug.txt" den Dateinamen anhängen willst. Solltest du auch den Slash im String mit einfügen.

Edit
Ok ich habe das Plus 1 übersehen.
 
Zuletzt bearbeitet:
Ich würde gleich das Pfad Objekt verwenden. Das macht das Manipulieren von Pfaden einfacher und ist unabhängig von dem Filesystem in dem man arbeitet, z.B Windows, Linux oder ZIP.
Java:
Path aktPfad = Paths.get("d:\\test\\input.txt");
        
        Path pathParent = aktPfad.getParent(); //Parent Verzeichnis ermitteln
        //Falls Parent == null ->  tempPath ist Dateiname; sonst nehme pathParent und hänge Dateiname an.
        Path tempPath = pathParent == null ? Paths.get("bug.txt") : pathParent.resolve("bug.txt");
        Path tempFile = null;
        
                try {
            tempFile = Files.createFile(tempPath);
        } catch (IOException e) {
            // normal handling of IOExceptions
            e.printStackTrace();
        }
Files.createTempFile ist für Dateien im Temp-Bereich vorgesehen. Ich würde die Datei eher normal erzeugen. Mit createTempFile müsste es dann so aussehen:
Code:
tempFile = Files.createTempFile(tempPath, "bug", "txt");
 
Kleiner Nachtrag: Natürlich sollte man von Anfang mit Pahts arbeiten:
Nicht
Code:
Path aktPfad = Paths.get("d:\\test\\input.txt");
Path aktPfad = Paths.get("d:\\test\\input.txt");
sondern:
Code:
Path aktPfad = Paths.get("d:", "test", "input.txt");
 
Ein großes Danke Euch allen!

Eine solche Resonanz habe ich nicht erwartet. Ich habe mich ziemlich ungeschickt angestellt und bin jetzt dank Eurer Ratschläge um einiges klüger. Die Lösung sieht jetzt so aus, wie von Michael Schusser empfohlen:

Java:
if (!eintrag) {
    String sTemp = aktPfad.substring(0, aktPfad.lastIndexOf(File.separator));
    Path outputPfad = Paths.get(sTemp, "bug.txt");
    Files.delete(outputPfad);
}

Gruß und nochmals vielen Dank
kodela
 
Eine Frage hätte ich noch in diesem Zusammenhang:
Den Code der Klasse, um den es hier ging, habe ich vor fast genau fünf Jahren geschrieben und es gab damit nie ein Problem. Als ich mich heute wieder mit diesem Code beschäftigte fiel mir etwas auf:

Es wird eine Datei für den Input geöffnet, hier der Code:

Java:
try (FileReader fr = new FileReader(pfad);
    BufferedReader br = new BufferedReader(fr)) {
    do {
         . . .
    } while (zeile != null);
    br.close();
    fr.close();
}

Hier wird in "pfad" der komplette Pfad (als String) für die zu öffnende Datei übergeben.

Zuvor wird allerdings die Datei geöffnet, um deren Entfernung es in diesem Thread ging und zwar mit folgendem Code:

Code:
fw = new FileWriter("unberuecksichtigt.txt");
bw = new BufferedWriter(fw);

Hier wird nur der Dateiname, nicht der komplette Pfad verwendet. Erzeugt wird diese Datei jedoch im selben Ordner, wie die vorgenannte Datei für den Input. Wenn ich diese Datei allerdings lösche, muss der vollständige Pfad angegeben werden.

Warum wird die Output-Datei ohne komplette Pfadangabe im richtigen Ordner, dem Arbeitsordner der Anwendung, erzeugt, in dem auch die Input-Datei liegt?
 
Ja, danke, das ist tatsächlich so und ich kann daher meinen Code an einigen Stellen vereinfachen. Im diskutierten Beispiel sieht das dann so aus:

Java:
if (!eintrag) {
    Path outputPfad = Paths.get("bug.txt");
    Files.delete(outputPfad);
}

oder noch kürzer:

Java:
if (!eintrag) {
    Files.delete(Paths.get("bug.txt");
}

Für den Input gilt dies bei mir nicht, der kann ja von irgendwo stammen.
 
Zuletzt bearbeitet:
Versuche grundsätzlich, keine Dateien in deinem Ausführungsverzeichnis zu verändern.
Sollte dein Programm irgend wann nämölich mal z.B. aus "c:\Program Files" ausgeführt werden, kriegst du damit ein Problem. Dann werden Administratorrechte fällig, da nur der Admin da reinschreiben darf.

Sofern möglich, arbeite immer in den dafür vorgesehen Verzeichnissen. Auf einem Windows-System hol dir den Inhalt der Systemvariablen
%appdata% und %localappdata%. Diese verweisen im Normalfall auf "%userprofile%\AppData\Roaming" und "%userprofile%\AppData\Local"
Auf älteren Windows Systeme gibt es nur eine Variable, "Roaming" und "Local" fallen weg.
Unter Linux oder Mac gibt's auch entsprechende Variablen.

Erstelle dann dort entsprechend den Konventionen eine Verzeichnis zum Arbeiten, z.B.
%appdatalocal%/org/thisisme/MeinProgrammName

Das mit der Temp-Datei hast du schon mal gut gemacht, viele würden auch hier eine Datei im Programmverzeichnis anlegen.
 
Das mit der Temp-Datei hast du schon mal gut gemacht, viele würden auch hier eine Datei im Programmverzeichnis anlegen.
Wobei er da vermutlich das Problem nicht gelöst bekommen hat. Zumindest ich sehe nicht, dass er da die Parameterliste irgendwie angepasst hat. Und der Versuch, bei einem temporären File Pfad/Dateiname anzugeben, ist auch nicht wirklich zielführend. Die Dokumentation beschreibt die Parameter ja richtig und da sind halt zwei Varianten vorhanden:
Mit mind. 3 Parametern:
  • Verzeichnis (Path)
  • Praefix (String)
  • Suffix (String)
  • Möglichkeit für Attribute (varargs Parameter).

Oder ohne den Path - dann wäre es nur:
  • Praefix (String)
  • Suffix (String)
  • Möglichkeit für Attribute (varargs Parameter).

Letzteres würde ich verwenden - dann landet das Temporäre File an dem für das System üblichen Ort.
 
Wobei er da vermutlich das Problem nicht gelöst bekommen hat. Zumindest ich sehe nicht, dass er da die Parameterliste irgendwie angepasst hat.
Ich meite rein die Idee, von Java eine Temporärdatei erstellen zu lassen 🙂 Über die Umsetzung lässt sich diskutieren.
Klar, er hat das noch nicht ganz verstanden und sollte sich wirklich mal die API Doku durchlesen, aber der reine Fakt, dass er es versucht hat, ist schon mehr, als andere zu bieten haben.

edit: Ja, die zweite Methode ist die, die ich empfehlen würde und auch verwende, wenn ich was brauche.
 
Versuche grundsätzlich, keine Dateien in deinem Ausführungsverzeichnis zu verändern.
Sollte dein Programm irgend wann nämölich mal z.B. aus "c:\Program Files" ausgeführt werden, kriegst du damit ein Problem. Dann werden Administratorrechte fällig, da nur der Admin da reinschreiben darf.

Sofern möglich, arbeite immer in den dafür vorgesehen Verzeichnissen. Auf einem Windows-System hol dir den Inhalt der Systemvariablen
%appdata% und %localappdata%. Diese verweisen im Normalfall auf "%userprofile%\AppData\Roaming" und "%userprofile%\AppData\Local"
Auf älteren Windows Systeme gibt es nur eine Variable, "Roaming" und "Local" fallen weg.
Unter Linux oder Mac gibt's auch entsprechende Variablen.

Erstelle dann dort entsprechend den Konventionen eine Verzeichnis zum Arbeiten, z.B.
%appdatalocal%/org/thisisme/MeinProgrammName

Das mit der Temp-Datei hast du schon mal gut gemacht, viele würden auch hier eine Datei im Programmverzeichnis anlegen.

Danke für die wertvollen Hinweise von Dir und auch von @KonradN. Ich werde mich vor allem für eventuell künftige Projekte sicher an sie erinnern.
Mein derzeitiges Projekt ist nach ziemlich genau fünf Jahren so gut wie abgeschlossen. Da werde ich wohl nicht mehr viel ändern.

Gruß, kodela
 

Neue Themen


Zurück
Oben