Ich habe ein Verzeichnis, das Dateien enthält, die an Clients geliefert werden, sagen wir /srv/data
. Während ich eine Reihe von Aktualisierungen mache, arbeite ich an /srv/data_tmp
, und am Ende der Operation möchte ich data
mit data_tmp
atomar ersetzen. File.renameTo()
gibt immer false für mich zurück, wenn das Ziel ein vorhandenes Verzeichnis ist. Wie kann ich das machen?Wie ersetzt man in Java ein Verzeichnis atomar durch ein anderes?
Antwort
Ich fürchte, Sie können nicht. Zumindest nicht auf der SO-Ebene. Selbst wenn Sie "Atomizität" im Kontext Ihrer Java-Anwendung verwalten, haben Sie keine Garantie, dass ein anderer "Rogue" -Prozess auf der Ebene des tatsächlichen Dateisystems stört.
Wenn ich Sie wäre, würde ich lesen this article (ziemlich alt, aber sollte Ihnen einige Ideen geben) und dann sehen, ob Sie den vorgeschlagenen Ansatz zu einem more modern version portieren können.
Oh, warte, jemand hat schon this!
Und anscheinend Sie nicht the first one to ask here, entweder
Best of luck ...
Die Apache Commons-Transaktionen erlauben mir, dies zu tun Dies ist sehr übersichtlich, wenn auch nur im Kontext meiner Java App, was mir jetzt reicht. Danke für deinen Link! –
Sie könnten das Verzeichnis /srv/data
durch einen symbolischen Link (oder einen junction in Windows XP) ersetzen und das Ziel des Links ändern, falls dies sinnvoll ist. Sie können dies jedoch nicht mit einer Java 6-API tun - Sie müssten sich auf eine Bibliothek verlassen oder die Befehlszeilenbefehle selbst schreiben.
NB: Ich garantiere nichts über die Atomarität dieser Operation.
Der Symbolik-Link-Ansatz ist interessant, aber Sie irren sich damit, dass Sie eine Datei nicht in eine Datei umbenennen können, die bereits existiert. Wenn sowohl a als auch b in "/ home/me" existieren, überschreibt dies erfolgreich b mit einem (unter Mac OS X/HFS +): 'new File ("/home/me/a "). RenameTo (neue Datei ("/home/me/b ")' –
Oh, richtig, habe das nicht erwartet. –
Der Linux-Systemaufruf rename
erlaubt dies nicht (der Systemaufruf rename
kann nur ein leeres Verzeichnis überschreiben), also bezweifle ich, dass es in Java unter Linux möglich ist.
Ist der Aufruf zum 'atomaren' Umbenennen? Und wenn ja, auch beim Überschreiben? –
Ja, aber laut [man-Seite ] (http://linux.die.net/man/2/rename) "Beim Überschreiben wird es wahrscheinlich ein Fenster geben, in dem sowohl oldpath als auch newpath auf die Datei verweisen, die umbenannt wird." –
Zur Erreichung dieses Ziels ist durchaus möglich, eine Kombination aus "Symlink" verwenden und "Umbenennen", zusammen mit einem Zwischen tmp Verzeichnis. Das folgende Beispiel ist in der Schale, aber man konnte die Funktionalität hier leicht übersetzen, die zugrunde liegenden Anrufe zu verwenden:
mkdir -p tmp/real_dir1 tmp/real_dir2
touch tmp/real_dir1/a tmp/real_dir2/a
# start with ./target_dir pointing to tmp/real_dir1
ln -s tmp/real_dir1 target_dir
# create a symlink named target_dir in tmp, pointing to real_dir2
ln -sf tmp/real_dir2 tmp/target_dir
# atomically mv it into ./ replacing ./target_dir
mv tmp/target_dir ./
Beispiel hier entnommen aus: http://axialcorps.wordpress.com/2013/07/03/atomically-replacing-files-and-directories/
Dies läuft darauf hinaus (in Pseudocode):
mkdir('./tmp');
mkdir('./tmp/real_dir1');
mkdir('./tmp/real_dir2');
symlink('./tmp/real_dir1', './target_dir')
symlink('./tmp/real_dir2', './tmp/target_dir')
rename('./tmp/target_dir', './target_dir')
Die endgültige Umbenennung ist hier atomar, so dass die Aktion entweder erfolgreich ist oder ganz fehlschlägt, da die Aktion von dem Punkt eines Prozesses, der das Verzeichnis verwendet, atomar ist.
- 1. Wie ersetzt man ein Tabellenfeld durch ein anderes?
- 2. Java - atomar löscht ein (nicht leeres) Verzeichnis
- 3. Wie wird ein DialogFragment durch ein anderes DialogFragment ersetzt?
- 4. Wie schreibe ich ein Batch-Skript, das ein Verzeichnis in ein anderes kopiert, ersetzt alte Dateien?
- 5. Schöne Suppe 4: Wie man ein Tag durch Text und ein anderes Tag ersetzt?
- 6. Wie man ein Fragment durch ein anderes auf ListView Element ersetzt klicken Sie auf Android
- 7. Wie ersetzt man ein Verzeichnis mit einem Symlink mit Ansible?
- 8. Cygwin in ein anderes Verzeichnis zu extrahieren
- 9. Wie ersetzt man Root-ebs-Volume durch ein anderes Root-ebs-Volume?
- 10. Wie kopieren wir ein ganzes Verzeichnis in ein anderes Verzeichnis in Maven?
- 11. Dekomprimieren mehrere gz in ein anderes Verzeichnis
- 12. git: stash in ein anderes Verzeichnis verschieben
- 13. Amazon S3 kopiert das Verzeichnis in ein anderes Verzeichnis
- 14. Wie man durch & in Perl ersetzt?
- 15. Makefile: Kompilieren aus dem Verzeichnis in ein anderes Verzeichnis
- 16. So kopieren Sie eine Datei aus einem Verzeichnis in ein anderes Verzeichnis in Java
- 17. parse_url ersetzt das Pluszeichen durch ein Leerzeichen
- 18. Wie ersetzt man '& =' durch '= &' in Vim?
- 19. iOS: Wie man "\" durch "/" in NSString ersetzt?
- 20. Kopieren Sie ein Verzeichnis auf ein anderes Laufwerk
- 21. Wie kopiere ich Dateien mit MSBuild in ein anderes Verzeichnis?
- 22. Wird in Golang ein Zeiger atomar zugewiesen?
- 23. MATLAB: wie man ein Bild in ein anderes Bild umwandelt
- 24. Java - Wie ersetzt man Dateiinhalte?
- 25. Wie erstellt man ein Verzeichnis in Wix?
- 26. Wie ersetzt man die Instanz der Zeichenfolge in SQL Server, wenn ein anderes Muster folgt?
- 27. Wie ersetzt man ein oder mehrere aufeinanderfolgende Leerzeichen durch ein einzelnes Zeichen?
- 28. Wie man $ httpBackend durch alternativen Scheinserver ersetzt?
- 29. Verwendung xargs ein Verzeichnis von Fundergebnisse in ein anderes Verzeichnis mv
- 30. Wie zeichne ich ein Bild über ein anderes Bild?
Haben Sie Einschränkungen für das zugrunde liegende Dateisystem? Offensichtlich, wenn es FAT ist, gibt es keine Möglichkeit, da das Dateisystem es nicht unterstützt. Weißt du, ob sich die beiden Verzeichnisse auf demselben physischen Volume befinden? Können Sie die neuen JDK7 java.nio.file APIs verwenden oder muss es auf einem JDK <= 6 arbeiten? –
Ich glaube nicht, dass zwei Dateiverschiebeoperationen "atomar" im engeren Sinne des Wortes durchgeführt werden können. Einige Dateisysteme garantieren einige [atomare Operationen] (http://www.softpanorama.org/Internals/Filesystems/ntfs.shtml), aber ich kenne keine Möglichkeit, an das Betriebssystem zu verlangen, dass mehrere FS-Aktionen für alle atomar ausgeführt werden Prozesse; sicherlich nicht in Java. – maerics
@Mike: Ich werde HFS +, ext3 oder NTFS, nie FAT verwenden. Es sollte mit JDK 6 funktionieren. –