Prevent file channel from closing after reading xml file

╄→尐↘猪︶ㄣ 提交于 2019-12-03 18:15:40

问题


For more detailed information regarding the motivation behind this goal (and my efforts to solve it) view my previous question. I decided to ask this as a new question entirely as I thought that it had evolved sufficiently to merit doing so. As a summary, I intend to use JDOM in combination with NIO in order to:

  1. Gain an exclusive file lock on an xml file.
  2. Read the file into a Document object.
  3. Make arbitrary changes (with lock still active!).
  4. Write the changes back to the xml file.
  5. Release the file lock.

The issue which I am getting however is that the built-in code to read the xml file into a document object closes the channel (and therefore releases the lock), as seen below:

import java.io.*;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import javax.xml.parsers.*;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

public class Test4{ 
    String path = "Test 2.xml";
    private DocumentBuilderFactory dbFactory;
    private DocumentBuilder dBuilder;
    private Document doc;

    public Test4(){
        try (final FileChannel channel = new RandomAccessFile(new File(path), "rw").getChannel()) {
            dbFactory = DocumentBuilderFactory.newInstance();
            dBuilder = dbFactory.newDocumentBuilder();

            System.out.println(channel.isOpen());
            doc = dBuilder.parse(Channels.newInputStream(channel));
            System.out.println(channel.isOpen());

            channel.close();
        } catch (IOException | ParserConfigurationException | SAXException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args){
        new Test4();
    }
}

Output:

true
false

Having looked through the documentation and trawled the built in Java libraries, I am really struggling to even find where the channel is closed, let alone how to prevent it closing. Any pointers would be great! Thanks.


回答1:


One clean way to do this is to create a FilterInputStream and override the close to do nothing:

public Test() {
    try {
        channel = new RandomAccessFile(new File(path), "rw").getChannel();
        dbFactory = DocumentBuilderFactory.newInstance();
        dBuilder = dbFactory.newDocumentBuilder();

        System.out.println(channel.isOpen());
        NonClosingInputStream ncis = new NonClosingInputStream(Channels.newInputStream(channel));
        doc = dBuilder.parse(ncis);
        System.out.println(channel.isOpen());
        // Closes here.
        ncis.reallyClose();
        channel.close(); //Redundant
    } catch (IOException | ParserConfigurationException | SAXException e) {
        e.printStackTrace();
    }
}

class NonClosingInputStream extends FilterInputStream {

    public NonClosingInputStream(InputStream it) {
        super(it);
    }

    @Override
    public void close() throws IOException {
        // Do nothing.
    }

    public void reallyClose() throws IOException {
        // Actually close.
        in.close();
    }
}



回答2:


Did you try the try-with-ressource statment? Even though, this is not the main purpose of this feature, maybe that does what you are looking for (in form of auto closing the ressources (your channel), but only when you leave the corresponding try-block)

try (final Channel channel = new RandomAccessFile(new File(path), "rw").getChannel()) {
  // your stuff here
} catch (IOException ex) {
  ex.printStackTrace();
}


来源:https://stackoverflow.com/questions/26605671/prevent-file-channel-from-closing-after-reading-xml-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!