java file path



Zuverlässige File.renameTo() Alternative unter Windows? (10)

Javas File.renameTo() ist problematisch, besonders unter Windows. Wie die API-Dokumentation sagt,

Viele Aspekte des Verhaltens dieser Methode sind plattformabhängig: Die Umbenennungsoperation ist möglicherweise nicht in der Lage, eine Datei von einem Dateisystem in ein anderes zu verschieben, sie ist möglicherweise nicht atomar und möglicherweise nicht erfolgreich, wenn eine Datei mit dem abstrakten Zielpfadpfad vorhanden ist ist bereits vorhanden. Der Rückgabewert sollte immer überprüft werden, um sicherzustellen, dass der Umbenennungsvorgang erfolgreich war.

In meinem Fall muss ich als Teil eines Upgrade-Vorgangs ein Verzeichnis verschieben (umbenennen), das Gigabytes an Daten enthalten kann (viele Unterverzeichnisse und Dateien unterschiedlicher Größe). Die Verschiebung erfolgt immer innerhalb der gleichen Partition / des gleichen Laufwerks. Es ist also nicht erforderlich, alle Dateien auf der Festplatte physisch zu verschieben.

Es sollte keine Dateisperren für den Inhalt des Verzeichnisses geben, das verschoben werden soll, aber oft kann renameTo () seine Aufgabe nicht ausführen und gibt false zurück. (Ich vermute nur, dass einige Dateisperren unter Windows irgendwie willkürlich ablaufen.)

Derzeit habe ich eine Fallback-Methode, die Kopieren und Löschen verwendet, aber das ist sick, weil es je nach Größe des Ordners viel Zeit in Anspruch nehmen kann. Ich überlege auch, einfach zu dokumentieren, dass der Benutzer den Ordner manuell verschieben kann, um möglicherweise nicht stundenlang zu warten. Aber der richtige Weg wäre offensichtlich etwas automatisches und schnelles.

Meine Frage ist also, kennen Sie einen alternativen, zuverlässigen Ansatz, um einen schnellen Umzug / Umbenennung mit Java unter Windows entweder mit reinem JDK oder einer externen Bibliothek durchzuführen. Oder wenn Sie eine einfache Möglichkeit kennen, um Dateisperren für einen bestimmten Ordner und seinen gesamten Inhalt (möglicherweise tausende einzelner Dateien) zu erkennen und freizugeben, wäre das auch in Ordnung.

Edit : In diesem speziellen Fall scheint es, als wären wir mit der Verwendung von renameTo() davongekommen, indem wir ein paar weitere Dinge berücksichtigt haben; Siehe diese Antwort .

https://ffff65535.com


Das folgende Stück Code ist KEINE "Alternative", hat aber in Windows- und Linux-Umgebungen zuverlässig funktioniert:

public static void renameFile(String oldName, String newName) throws IOException {
    File srcFile = new File(oldName);
    boolean bSucceeded = false;
    try {
        File destFile = new File(newName);
        if (destFile.exists()) {
            if (!destFile.delete()) {
                throw new IOException(oldName + " was not successfully renamed to " + newName); 
            }
        }
        if (!srcFile.renameTo(destFile))        {
            throw new IOException(oldName + " was not successfully renamed to " + newName);
        } else {
                bSucceeded = true;
        }
    } finally {
          if (bSucceeded) {
                srcFile.delete();
          }
    }
}

Der ursprüngliche Post forderte "eine alternative, zuverlässige Methode, um eine schnelle Verschiebung / Umbenennung mit Java unter Windows durchzuführen, entweder mit reinem JDK oder einer externen Bibliothek."

Eine andere Option, die hier noch nicht erwähnt wurde, ist Version 1.3.2 oder höher der Bibliothek apache.commons.io , die FileUtils.moveFile() .

Es wird eine IOException ausgelöst, statt bei einem Fehler den Wert boolean false zurückzugeben.

Siehe auch die Antwort von big lep in diesem anderen Thread .


Ich hatte ein ähnliches Problem. Die Datei wurde kopiert, bewegte sich eher unter Windows, funktionierte aber gut unter Linux. Ich habe das Problem behoben, indem ich den geöffneten fileInputStream vor dem Aufruf von renameTo () geschlossen habe. Getestet unter Windows XP.

fis = new FileInputStream(originalFile);
..
..
..
fis.close();// <<<---- Fixed by adding this
originalFile.renameTo(newDesitnationForOriginalFile);

Ich weiß, dass das ein bisschen hacky aussieht, aber für das, wofür ich es gebraucht habe, scheint es, dass gepufferte Leser und Schreiber keine Probleme haben, die Dateien zu erstellen.

void renameFiles(String oldName, String newName)
{
    String sCurrentLine = "";

    try
    {
        BufferedReader br = new BufferedReader(new FileReader(oldName));
        BufferedWriter bw = new BufferedWriter(new FileWriter(newName));

        while ((sCurrentLine = br.readLine()) != null)
        {
            bw.write(sCurrentLine);
            bw.newLine();
        }

        br.close();
        bw.close();

        File org = new File(oldName);
        org.delete();

    }
    catch (FileNotFoundException e)
    {
        e.printStackTrace();
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }

}

Funktioniert gut für kleine Textdateien als Teil eines Parsers. Stellen Sie nur sicher, dass alterName und neuerName vollständige Pfade zu den Dateipositionen sind.

Prost Kaktus


In meinem Fall lag der Fehler im Pfad des übergeordneten Verzeichnisses. Vielleicht ein Fehler, ich musste die Teilzeichenfolge verwenden, um einen korrekten Pfad zu erhalten.

        try {
            String n = f.getAbsolutePath();
            **n = n.substring(0, n.lastIndexOf("\\"));**
            File dest = new File(**n**, newName);
            f.renameTo(dest);
        } catch (Exception ex) {
           ...

In meinem Fall schien es ein totes Objekt in meiner eigenen Anwendung zu sein, das einen Griff zu dieser Datei behielt. So hat diese Lösung für mich funktioniert:

for (int i = 0; i < 20; i++) {
    if (sourceFile.renameTo(backupFile))
        break;
    System.gc();
    Thread.yield();
}

Vorteil: Es ist ziemlich schnell, da es kein Thread.sleep () mit einer bestimmten fest codierten Zeit gibt.

Nachteil: diese Grenze von 20 ist eine fest codierte Zahl. In allen meinen Tests ist i = 1 genug. Aber natürlich habe ich es um 20 Uhr verlassen.


Siehe auch die Files.move() -Methode in JDK 7.

Ein Beispiel:

String fileName = "MyFile.txt";

try {
    Files.move(new File(fileName).toPath(), new File(fileName).toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ex) {
    Logger.getLogger(SomeClass.class.getName()).log(Level.SEVERE, null, ex);
}

Um eine Datei zu verschieben / umzubenennen, können Sie diese Funktion verwenden:

BOOL WINAPI MoveFile(
  __in  LPCTSTR lpExistingFileName,
  __in  LPCTSTR lpNewFileName
);

Es ist in kernel32.dll definiert.


Warum nicht....

import com.sun.jna.Native;
import com.sun.jna.Library;

public class RenamerByJna {
    /* Requires jna.jar to be in your path */

    public interface Kernel32 extends Library {
        public boolean MoveFileA(String existingFileName, String newFileName);
    }

    public static void main(String[] args) {
        String path = "C:/yourchosenpath/";
        String existingFileName = path + "test.txt";
        String newFileName = path + "renamed.txt";

        Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
            kernel32.MoveFileA(existingFileName, newFileName);
        }
}

arbeitet auf nwindows 7, tut nichts, wenn existingFile nicht existiert, aber könnte offensichtlich besser instrumentiert sein, um das zu beheben.


 File srcFile = new File(origFilename);
 File destFile = new File(newFilename);
 srcFile.renameTo(destFile);

Das obige ist der einfache Code. Ich habe auf Windows 7 getestet und funktioniert einwandfrei.





file-io