content of XML file created by java app dissapears if computer is shut down
I developed a desktop application, which has a class that reads a XML file (using DOM), then performs some operations to the data, and saves the data back to XML (replacing previous file). This class is instantiated and the method invoked every 30 seconds. The problem I have is that if the computer running the application is shutdown (suddenly with the power button, not properly). then, when pc starts again, the XML file is empty. A blank file remains. This doesn't happen every single time the computer is shut down, but very often though. If the computer is properly turned off, this never happens. This is the code:
private org.w3c.dom.Document dom;
private javax.xml.parsers.DocumentBuilder db;
public PlayerConfigHandler() {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
db = dbf.newDocumentBuilder();
dom = db.newDocument();
} catch (Exception e) { }
}
public void updateConfig(List<File> playlists) {
String playerPath = Preferences.getInstance().readStringProperty("PlayerDirectory");
File configuration = new File(playerPath + "\\playerconfiguration.sdpp"); // replace with configuration path
if(!configuration.exists()) {
Logger.getLogger(PlayerConfigHandler.class).info("File " + configuration
+ " does not exist! Unable to update it.");
return;
}
dom = db.newDocument();
InputStream is = null;
Reader reader = null;
try {
is = new FileInputStream(configuration);
reader = new InputStreamReader(is);
InputSource source = new InputSource(reader);
dom = db.parse(source);
} catch (SAXException ex) {
Logger.getLogger(PlayerConfigHandler.class).error("updateConfig(). SAXException reading XML file: " + ex);
return;
} catch (IOException ex) {
Logger.getLogger(PlayerConfigHandler.class).error("updateConfig(). IOException reading XML file: " + ex);
return;
} catch(Exception ex) {
Logger.getLogger(PlayerConfigHandler.class).error("updateConfig(). Exception reading XML file: " + ex);
return;
} finally {
try {
reader.close();
is.close();
} catch (Exception e) {
Logger.getLogger(PlayerConfigHandler.class).error("Exception closing FileInputStream/Reader after reading XML file: " + e);
}
}
Element element = dom.getDocumentElement();
//perform some operations to the data read...
FileOutputStream outputStream = null;
try {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
transformerFactory.setAttribute("indent-number", 4);
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty("encoding","ISO-8859-1");
Source source = new DOMSource(dom);
outputStream = new FileOutputStream(configuration);
Result result = new StreamResult(new OutputStreamWriter(outputStream));
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.transform(source, result);
} catch (TransformerConfigurationException tce) {
Logger.getLogger(PlayerC开发者_高级运维onfigHandler.class).error("Exception saving XML file: " + tce);
} catch (TransformerException te) {
Logger.getLogger(PlayerConfigHandler.class).error("Exception saving XML file: " + te);
} catch (FileNotFoundException fe) {
Logger.getLogger(PlayerConfigHandler.class).error("Exception saving XML file: " + fe);
} catch(Exception e) {
Logger.getLogger(PlayerConfigHandler.class).error("Exception saving XML file: " + e);
}
finally {
try {
outputStream.close();
} catch (Exception e) {
Logger.getLogger(PlayerConfigHandler.class).error("Exception closing FileOutputStream after writing XML file: " + e);
}
}
dom = db.newDocument();
}
Any idea of why this happens? Is there anything wrong in the code? Is there any way to prevent this? Thanks, Damian
The new FileOutputStream
is truncating the file and the computer is turned off before any new data is written and closed. This simple example demonstrates the problem. If you run this once, edit foo.txt
then run it again, the contents will be truncated.
import java.io.*;
public class FileCreate {
public static void main(String[] args) throws Exception {
File f = new File("C:\\temp\\foo.txt");
FileOutputStream outputStream = new FileOutputStream(f);
outputStream.close();
}
}
One way to resolve this is to write the new configuration to a different file and then perform a "delete" and "rename".
When the program opens the file to write, it clears out the contents of the file.
If the computer shuts off after this occurs, but before you close the stream, it is very likely that any data you have written does not get flushed to the file before termination.
To prevent such thing, you could open your file and read it, perform some operations, save it in another file, and them replace the first file with the second (like a rename
).
This way, when you turn the computer off, you'll have the old file.
But this is not super-secure: there might happen to turn the computer off in the moment it's replacing the file, leaving you with an corrupted file instead.
精彩评论