我正在用Java编写一个小程序,将数据写入XML文件。由于有多个用户启动它,我需要在写入之前锁定xml文件。所以我写得那样:
if (new File(path).exists()) {
try {
FileChannel channel = new RandomAccessFile(new File(path), "rw")
.getChannel();
java.nio.channels.FileLock lock = channel.lock();
DocumentBuilderFactory docFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(path);
// Get the root element
Node economato = doc.getFirstChild();
NodeList protocolli = doc.getElementsByTagName("numero");
if (protocolli.getLength() == 0)
p.setNumero(1);
else
p.setNumero(protocolli.getLength()+1);
Element protocolloNode = doc.createElement("protocollo");
economato.appendChild(protocolloNode);
Element protocolloNumero = doc.createElement("numero");
protocolloNumero.appendChild(doc.createTextNode(Integer
.toString(p.getNumero())));
protocolloNode.appendChild(protocolloNumero);
Element protocolloData = doc.createElement("data");
protocolloData.appendChild(doc.createTextNode(p.getData()));
protocolloNode.appendChild(protocolloData);
Element protocolloObj = doc.createElement("oggetto");
protocolloObj.appendChild(doc.createTextNode(p.getOggetto()));
protocolloNode.appendChild(protocolloObj);
Element protocolloDest = doc.createElement("destinatario");
protocolloDest.appendChild(doc.createTextNode(p
.getDestinatario()));
protocolloNode.appendChild(protocolloDest);
Element protocolloOp = doc.createElement("operatore");
protocolloOp.appendChild(doc.createTextNode(p.getOperatore()));
protocolloNode.appendChild(protocolloOp);
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(path);
transformer.transform(source, result);
lock.release();
channel.close();
JOptionPane.showMessageDialog(this.fatherFrame,
"Nuovo protocollo salvato correttamente!");
} catch (ParserConfigurationException pce) {
pce.printStackTrace();
} catch (TransformerException tfe) {
tfe.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (SAXException sae) {
sae.printStackTrace();
}
}
我试图在Linux Debian中启动,一切正常。 相反,如果我在Windows 7中尝试,我会收到此错误:
java.io.IOException: The process cannot access the file because another process has locked a portion of the file
at java.io.FileInputStream.readBytes(Native Method)
a java.io.FileInputStream.read(Unknown Source)
at java.io.BufferedInputStream.fill(Unknown Source)
at java.io.BtufferedInputStream.read(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager$RewindableInputStream.read(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
at javax.xml.parsers.DocumentBuilder.parse(Unknown Source)
at it.questura.economato.InsertListener.actionPerformed(InsertListener.java:77)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
但是没有其他进程阻止该文件。我只启动了我的程序的一个实例,所以它是唯一的...哪个进程可以锁定文件?
--- --- EDIT 我唯一的解决方案是使用一个名为LOCK的“令牌文件”。你获得了名为LOCK的文件上的通道上的锁,然后你可以在真正的file.xml上读/写...然后你释放LOCK文件上的锁...它似乎工作但我发现它很愚蠢笨。 有什么更好的吗?我还在一个论坛中读到,我可以将文件通道读取()到ByteBuffer中,然后从支持它的byte []创建一个ByteArrayInputStream。然后将流传递给DocumentBuilder。但是当我创建一个ByteBuffer时,在我应该分配它的字节数之前......我怎么能事先知道file.xml有多少字节?
答案 0 :(得分:1)
请勿使用parse(String path)
。使用带有Reader或InputStream的方法并将FileChannel包装在其中。
像这样:Channels.newInputStream(channel)
答案 1 :(得分:0)
FileLock fileLock = null;
FileChannel fileChannel = null;
try {
fileChannel = FileChannel.open(path, StandardOpenOption.READ,
StandardOpenOption.WRITE);
fileLock = fileChannel.tryLock();
inputStream = Channels.newInputStream(fileChannel);