Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
860 views
Welcome To Ask or Share your Answers For Others

1 Answer

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();
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...