Kickaha
Kickaha

Reputation: 3857

Java "File" works but "InputStream" does not

EDIT: getResourceAsStream() vs FileInputStream

Is the best explanation I have found. Personally after trying all the different subclasses of InputStream I feel the implementation of the InputStream returned by FileInputstream() and the one returned by getResourceAsStream() are subtly different in some way (causing an incompatibility with javax.xml.parsers.. )

I'll leave this open for a while just in case someone happens to have an answer, but I'm done. thanks for all the advice, suggestions and help. Time too move on to the next thing.


I've have a servlet which collects it's initialization data from an XML ini file, it opens it as an InputStream from the servlet session context like this

   HttpSession session = request.getSession(true);
   ServletContext ctx=session.getServletContext();
   InputStream myini = ctx.getResourceAsStream("/WEB-INF/myini.xml");

That works, but later on I'm writing JUnit tests and in the setup function, and I need to access this same ini. I don't have the servlet context in the test environment so I try to create an InputStream using

InputStream testing = new FileInputStream(String pathToFile);

and also

InputStream testing = new FileInputStream(File fileObj); 

The exception thrown from the XML parser (below)

I find it impossible to get an InputStream for my init file and am forced to use File.

I checked the javadoc's, moved the file location in case of security restrictions. Eventually added dual constructors to the classes needing the ini, to accept both File and InputStream to cater for unit testing (where I need the File ref)and runtime (where the InputStream is returned from the servlet session context) ...

But i'm perplexed/pretty frustrated so I have to ask

How come I can return a file object using "File", which can then be successfully parsed by the javax.xml.parsers (see function below)

File myini = new File("C:\\apache-tomcat-7.0.30\\myini\\myini.xml");

But I cannot do the same with this using "InputStream" ?

InputStream myini = new FileInputStream("C:\\apache-tomcat-7.0.30\\myini\\myini.xml");

Using the exactly the same String path (i.e. the file exists)

Respectively each gets passed to either

public xmlNode parse(InputStream is) throws xmlException {
        try {
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            document = dBuilder.parse(is);
            document.getDocumentElement().normalize();

            xmlNode node = new xmlNode(document.getDocumentElement());
            return node;
        } catch (ParserConfigurationException e) {
            throw new xmlException("Error in configuration of XML parser", e);
        } catch (SAXException e) {
            throw new xmlException("Error in parsing XML document", e);
        } catch (IOException e) {
            throw new xmlException("Error in reading InputStream", e);
        }
    }

Or

public xmlNode parse(File file) throws xmlException {
        try {
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            document = dBuilder.parse(file);
            document.getDocumentElement().normalize();

            xmlNode node = new xmlNode(document.getDocumentElement());
            return node;
        } catch (ParserConfigurationException e) {
            throw new xmlException("Error in configuration of XML parser", e);
        } catch (SAXException e) {
            throw new xmlException("Error in parsing XML document", e);
        } catch (IOException e) {
            throw new xmlException("Error in opening file", e);
        }
    }

This Exception gets thrown only when the InputStream method is called (after the appropriate initialization as above)

xml.utils.xmlException: Error in reading InputStream
    at xml.utils.xmlDocument.parse(xmlDocument.java:40)
    at com.jcando.util.XMLini.<init>(XMLini.java:49)

Is there a different way of defining the path as a string for the InputStream ? Is there a security block I'm unaware of?

If someone can explain what I am missing, or where I am being thick as a stump I'd appreciate it.

Upvotes: 3

Views: 3330

Answers (3)

Kickaha
Kickaha

Reputation: 3857

getResourceAsStream() vs FileInputStream

Is the best explanation I have found. Personally after trying all the different subclasses of InputStream I feel the implementation of the InputStream returned by FileInputstream() and the one returned by getResourceAsStream() are subtly different in some way (causing an incompatibility with javax.xml.parsers.. )

Upvotes: 0

Trevor Freeman
Trevor Freeman

Reputation: 7232

I suspect that you may have a character encoding error or an error related to resolving relative urls within your document (although I am not sure if that would cause an exception).

I think that you may want to look at trying something like:

InputSource source = new InputSource(is);
source.setEncoding(... your character encoding ...);
source.setSystemId(systemId);
dBuilder.parse(inputSource);

Where systemId is determined as file.toURI().toASCIIString().

Upvotes: 1

Jean Logeart
Jean Logeart

Reputation: 53829

You can always write File f = new File("anyName"): it will never throw an exception even if the file does not exist.

Yet, writing InputStream myini = new FileInputStream("anyName") will throw a FileNotFoundException exception if the file does not exist as you can see in the documentation.

Upvotes: 2

Related Questions