Frage

Ich habe ein bisschen von Java-Code, der eine XML-Datei in einem NFS-Dateisystem gemountet ausgibt. Auf einem anderen Server, die Dateisystem-montiert als Samba-Freigabe hat, ist es ein Prozess ausgeführt, dass für neue XML-Umfragen alle 30 Sekunden Dateien. Wenn eine neue Datei gefunden wird, wird es verarbeitet und dann als Backup-Datei umbenannt. 99% der Zeit, werden die Dateien ohne ein Problem geschrieben. jeder nun aber, und dann die Sicherungsdatei enthält eine teilweise geschrieben Datei.

Nach einiger Diskussion mit einigen anderen Menschen, ahnten wir, dass der Prozess auf dem externen Server ausgeführt wurde, mit dem Java-Ausgangsstrom zu stören, wenn es um die Datei zu lesen. Sie schlugen vor, zunächst eine Datei des Typs .temp zu schaffen, die dann wird umbenannt in .xml, nachdem die Datei Schreib abgeschlossen ist. Eine gemeinsame Industriepraxis. Nach dem Wechsel, schlägt der Umbenennungs jedes Mal.

Einige Untersuchungen aufgedreht, dass Java-Datei I / O-Buggy ist, wenn sie mit NFS arbeiten Dateisysteme montiert.

Helfen Sie mir Java-Gurus! Wie löse ich dieses Problem?

Hier sind einige relevante Informationen:

  • Mein Prozess ist Java 1.6.0_16 auf Solaris 10
  • Mounted-Dateisystem ist ein NAS
  • Server mit Abfrageprozess ist Windows Server 2003 R2 Standard, Service Pack 2

Hier ist eine Probe von meinem Code:

//Write the file
XMLOutputter serializer = new XMLOutputter(Format.getPrettyFormat());
FileOutputStream os = new FileOutputStream(outputDirectory + fileName + ".temp");
serializer.output(doc, os);//doc is a constructed xml document using JDOM
os.flush();
os.close();

//Rename the file
File oldFile = new File(outputDirectory + fileName + ".temp");
File newFile = new File(fileName + ".xml");
boolean success = oldFile.renameTo(newFile);
if (!success) {
    // File was not successfully renamed.
    throw new IOException("The file " + fileName + ".temp could not be renamed.");
}//if
War es hilfreich?

Lösung

Sie haben wahrscheinlich den vollständigen Pfad in den neuen Dateinamen angeben:

File newFile = new File(outputDirectory + fileName + ".xml");

Andere Tipps

Das sieht aus wie ein Bug zu mir:

File oldFile = new File(outputDirectory + fileName + ".temp");
File newFile = new File(fileName + ".xml");

ich erwartet hätte diese:

File oldFile = new File(outputDirectory + fileName + ".temp");
File newFile = new File(outputDirectory + fileName + ".xml");

In der Regel, es klingt wie eine Race-Bedingung Aufgabe zwischen dem Schreiben der XML-Datei und der Lese / Prozess / Umbenennungs ist. Können Sie die Schreib- / Prozess / Umbenennungs Aufgabe arbeitet auf Dateien> 1 Minute alt oder etwas ähnliches?

Oder hat das Java-Programm schreiben, eine zusätzliche, leere Datei, sobald es die XML-Datei zu schreiben out abgeschlossen hat, dass die Signale, dass das Schreiben in die XML-Datei abgeschlossen ist. Nur-Lese / Prozess / benennen Sie die XML-Datei, wenn die Signaldatei vorhanden ist. Dann löschen Sie die Signaldatei.

Der ursprüngliche Fehler definitiv klingt wie ein Problem mit dem gleichzeitigen Zugriff auf die Datei - Ihre Lösung gearbeitet haben sollte, aber es gibt auch alternative Lösungen.

Zum Beispiel, setzen Sie einen Timer auf Ihrem Auto-Lesevorgang, so dass es, wenn eine neue Datei erkannt wird es zeichnet Dateigröße, für X Sekunden, und dann, wenn die Größen neu startet den Timer nicht übereinstimmen. Das sollte Probleme mit teilweise Dateiübertragung vermeiden.

EDIT:. Oder überprüfen Sie die Zeitstempel wie vor darüber zu überprüfen, aber stellen Sie sicher, es ist alt genug, dass jede Ungenauigkeit bei der Zeitmarke spielt keine Rolle (zB 10 Sekunden bis 1 Minute seit dem letzten geändert)

Alternativ versuchen, diese:

File f = new File("foo.xml");
FileOutputStream fos = new FileOutputStream(f);
FileChannel fc = fos.getChannel();
FileLock lock = fc.lock();
(DO FILE WRITE)
fis.flush();
lock.release();
fos.close();

Diese native OS-Dateisperren verwenden, sollten Sie die gleichzeitigen Zugriff von anderen Programmen (wie zB XML-Leser-Daemon) zu verhindern.

Was NFS Glitches: Es gibt ein dokumentiertes „Feature“ (Bug), wo Dateien können nicht zwischen Dateisystemen über „Umbenennen“ in Java verschoben werden. Könnte es Verwirrung, da es auf einem NFS-Dateisystem?

ist

Einige Informationen zu NFS im Allgemeinen. Abhängig von Ihren NFS-Einstellungen, Sperren möglicherweise nicht an allen und vielen großen NFS-Installationen für die Leseleistung abgestimmt werden, damit neue Daten könnten auftauchen später als erwartet, aufgrund Cachen Effekte.

Ich habe Effekte gesehen, wo Sie eine Datei erstellt, addierten Daten (dies auf einer anderen Maschine zu sehen war), aber alle Daten danach mit einer 30 Sekunden Verzögerung erschienen.

Beste Lösung durch die Art und Weise ist ein rotierendes Dateischema. So dass der letzte wird angenommen, geschrieben werden und die davor war sicher geschrieben und gelesen werden können. Ich würde nicht auf einer einzelnen Datei arbeiten und es als „Rohr“ verwenden.

Sie können alternativ eine leere Datei verwenden, die nach der großen Datei geschrieben wurde geschrieben und richtig geschlossen. Also, wenn die kleinen Jungs da ist, wurde der große Kerl endgültig fertig und kann gelesen werden.

Möglicherweise aufgrund „Der Umbenennungsvorgang könnte nicht in der Lage sein, eine Datei von einem Dateisystem zum anderes zu bewegen“ von http://java.sun.com/j2se/1.5.0/docs/api/java/io/File .html # renameTo% 28java.io.File% 2 ) Versuchen Sie Apache commons io FiltUtils.copyFileToDirectory mit http://commons.apache.org/io/api-release/org/apache/commons/io/FileUtils.html#copyFileToDirectory (java.io.File, % 20java.io.File) statt

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top