In a j2ee web app one needs to read config files, test data files, or xml files or xslt files at run time. If you read them from a file directory, the directories may not be valid at run time inside the web app container. One can use the class loader instead to load these files. But I prefer to read them using the servlet context of an init servlet. The approach will also work for containers that only work with war files (WebSphere is an example).
String relativeFilename = "/somedir/somfile.xml";
InputStream is = ResourceReader.readResourceUsingRelativeURL(relativeFilename);
//work with is
is.close();
ResourceReader is a static class in which all the methods are static. The method here will read a file called "/somedir/somefile.xml" from the root of the web app.
public class ResourceReader
{
private static ServletContext m_ctx;
//Called from any int servlet's init method
public static void init(ServletContext ctx)
{
if (m_ctx == null)
{
m_ctx = ctx;
}
}
//if needed. Usually not required.
public static ServletContext getServletContext()
{
return m_ctx;
}
/**
* Given a relative url return an input stream for that url
* @param relativeUrl
* @return
*/
public static InputStream readResourceUsingRelativeURL(String relativeUrl)
{
return m_ctx.getResourceAsStream(relativeUrl);
}
/**
* Given an input stream return the contents of the stream as a string
* @param iStream
* @return
*/
public static String getContentsAsAString(String relativeUrl)
{
return readContents(
new BufferedReader(
new InputStreamReader(
readResourceUsingRelativeURL(relativeUrl))));
}
private static String readContents(BufferedReader input)
{
try
{
StringBuffer contents = new StringBuffer();
String line = null; //not declared within while loop
while ( (line = input.readLine()) != null)
{
contents.append(line);
contents.append(System.getProperty("line.separator"));
}
return contents.toString();
}
catch (IOException ex)
{
throw new RuntimeException("Could not read the input buffered reader",ex);
}
finally
{
//I am not sure why we are closing it, if we are not the owner
//of this resource
try
{
if (input != null)
{
//flush and close both "input" and its underlying Reader
input.close();
}
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
}
}//eof-class
You can improve upon the code a little bit. Closing the input stream is a bit sneaky in the above code. The closing of a stream should preferably be done by the owner of the stream.
public class InitServlet extends HttpServlet
{
public void init(ServletConfig config) throws ServletException
{
//set servlet context
ResourceReader.init(config.getServletContext());
}
}//eof-class