I have a Java webapp WAR file that depends on multiple jars in it's WEB-INF\lib directory. One of these JARS needs to load some config files by doing class.getClassLoader().getResourceAsStream(...). However the InputStream resturns null. Is there a problem with taking this approach when the JAR is inside a WAR? The app is deployed on Tomcat6.
EDIT MORE INFO:
I'm tring to load in SQL queries from files so I can run them. These are located in a separate DAO jar within the web app's WAR, under WEB-INF/lib
mywebapp.war
-- WEB-INF
-- lib
-- mydao.jar
---- com/companyname/queries
-- query1.sql
-- query2.sql
-- query3.sql
...
CODE USING TO LOAD CLASSES
public class QueryLoader {
private static final Logger LOGGER = Logger.getLogger(QueryLoader.class.getName());
public String loadQuery(String fileName) {
final String newline = "\n";
BufferedReader reader = new BufferedReader(new InputStreamReader(
QueryLoader.class.getClassLoader().getResourceAsStream(
"/com/companyname/queries/" + fileName)));
StringBuilder sb = new StringBuilder();
String line;
try {
while ((line = reader.readLine()) != null) {
sb.append(line);
sb.append(newline);
}
} catch (IOException e) {
LOGGER.error(e);
}
I have also tried changing the getResourceAsStream line to
Thread.currentThread().getContextClassLoader().getResourceAsStream(
without success.
My development environment is MS Windows Vista and but I encounter the same error when running it on this environment and on Ubuntu.
Assuming you're not making the rookie mistake of putting QueryLoader in a different JAR, the only problem I can see is that you're using File.separator yet appear (from your use of \) to be using Windows. When using getResourceAsStream, the separator is always a forward slash (/) just as if you're using a URL.
If I change that I get this:
QueryLoader.class.getClassLoader().getResourceAsStream(
"/com/companyname/queries/" + fileName)
Of course, if QueryLoader is in the com.companyname.queries package (along with the queries themselves) then you should simply do this:
QueryLoader.class.getResourceAsStream(fileName)
Simple as that. (It's documented that Class.getResourceAsStream qualifies relative filenames with the name of the containing package.)
Managed to get it to work by using Spring's resource loader instead
public String loadQuery(String fileName) {
final String newline = "\n";
ApplicationContext ctx = new ClassPathXmlApplicationContext();
Resource res = ctx.getResource("classpath:/com/msi/queries/" + fileName);
BufferedReader reader;
StringBuilder sb = new StringBuilder();
try {
reader = new BufferedReader(new InputStreamReader(res.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
sb.append(newline);
}
} catch (IOException e) {
LOGGER.error(e);
}
return sb.toString();
}
It should work, but you need to take care that you use the correct class loader.
Related
I'm trying to build a java program for both Android and JavaFX using a common core directory of code and a platform dependent section for each. One of these platform dependent options is called Resources, which is supposed to load text, image, and (eventually) audio files. The JavaFX version works great, and the skeleton of the program appears and can be used. However, the Android version won't doesn't display anything. I've traced that down to the fact that my resources aren't loading, throwing a variety of Exceptions, for the most part NullPointerExceptions. I'm not sure whether the problem is with the resources not being included or with giving it the wrong place to look in the program. My gradle file currently has the following relevant additions:
sourceSets {
main.java.srcDirs += '../../Both'
main.res.srcDirs += '../../Resources'
}
The ../../Both directory properly gets built into the code, as it properly builds and runs, and the Both Directory and the Android directory uses it.
However, the Resources, which include (for the most part), a number of Art subdirectories.
I have tried the following code for reading the files, mostly from the javafx equivalent (which works):
private static String getPath(String resource)
{
return "/Resources/"+resource;
}
public static ArrayList<String> loadText(String resource)
{
try{
if(filecache.containsKey(resource))
return filecache.get(resource);
InputStream in = R.getClass().getResourceAsStream(getPath(resource));
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
ArrayList<String> lines = new ArrayList<>();
String t;
while((t = reader.readLine()) != null)
lines.add(t);
filecache.put(resource, lines);
return lines;
} catch(Exception e){Debug.log(e.toString());}
return new ArrayList<>();
}
Using some code I found here, I have tried this as well, and a couple of variations of it, with no success. (using the same getPath() method)
ArrayList<String> res = new ArrayList<String>();
try {
InputStream inputStream = new android.content.res.Resources().(getPath(resource));
if ( inputStream != null ) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String receiveString = "";
while ( (receiveString = bufferedReader.readLine()) != null ) {
res.add(receiveString);
}
}
return res;
} catch(Exception e){Debug.log("While opening: " + resource);Debug.log(e);}
return new ArrayList<String>();
}
Both of those build, but throw Exceptions and don't load the files.
Any insights into how I might be able to read the files? Thanks!
Here it is my folder project
I would like to read the file book-form.html which is in the directory web of my project and put it in a String.
This is how I call my function 'getFileContent':
String content = getFileContent("web/book-form.html");
And this is the function:
public String getFileContent(String filePath){
String line, content = new String();
try {
File file = new File(filePath);
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
while((line = br.readLine()) != null){
content += line;
}
br.close();
fr.close();
} catch(IOException e){
System.out.println(e.getMessage());
}
return content;
}
My problem is that netbeans tell me that it cannot find my file book-form.html
Any ideas ?
File path to resource in our war/WEB-INF folder?
Also you should close stream in a final block or use try-with-resource if you use jdk 7+
I find the way to do it:
Basically the program is in the main folder of Glassfish, so it's needed to put the entire path of your file from the root of your system to allow the program to find your file.
I have an App Engine servlet which creates objects based on a JSON file (stored in a "Resources" folder under WEB-INF). I handle the parsing of the file in a separate class:
public class EventParser
{
static Gson gson = new Gson();
static String fileName = "/SOServices-war/src/main/webapp/WEB-INF/Resources/mockEvents.json";
static File file = new File(fileName);
public static List<Event> readDataFromJSON() throws IOException
{
InputStreamReader inReader = new InputStreamReader(new FileInputStream(file), "UTF-8");
String stringFromRes = null;
try (BufferedReader br = new BufferedReader(inReader))
{
StringBuilder sb = new StringBuilder();
String sCurrentLine;
while ((sCurrentLine = br.readLine()) != null)
{
sb.append(sCurrentLine);
sb.append(System.lineSeparator());
}
stringFromRes = sb.toString();
}
catch (IOException e)
{
e.printStackTrace();
}
List<Event> events = new ArrayList<Event>();
Type listOfTestObject = new TypeToken<List<Event>>(){}.getType();
events = gson.fromJson(stringFromRes, listOfTestObject);
return events;
}
}
It is important to point out that this used to work using "WEB-INF/" as path, but I've recreated the project (using the new Maven tutorial) and it has a new folder structure: instead of /war/WEB-INF, it looks like /AppName-war/src/main/webapp/WEB-INF. I don't really understand how it could affect things, but I can't seem to get file reading working again.
So far I've tried:
just using " instead of "WEB-INF/"
putting the files under the webapp folder directly
using the old method
using the string provided in this code snipped, but without the dash at the beginning
Neither of them worked, the files couldn't be found on local development environment (app is not deployed yet).
Update
Big thanks to McDowell for providing me the link, it was a bit different, but it helped a lot. I am now calling the readDataFromJSON() method with a servletContext parameter like so:
List<Event> events = EventParser.readDataFromJSON(this.getServletContext());
And then in the parser:
String filePath = context.getRealPath(fileName);
InputStreamReader inReader = new InputStreamReader(new FileInputStream(new File(filePath)), "UTF-8");
This solves my issue.
I have a project that finds a text file and makes it into an array of characters. However, for some reason or another it isn't finding the file. This is all the code involving opening/reading the file:
public void initialize(){
try{
File file = new File(getClass().getResource("/worlds/world1.txt").toString());
BufferedReader reader = new BufferedReader(
new InputStreamReader(
new FileInputStream(file),
Charset.forName("UTF-8")));
int c;
for(int i = 0; (c = reader.read()) != -1; i ++) {
for(int x = 0; x < 20; x++){
worlds[1][x][i] = (char) c;
c = reader.read();
}
}
}catch(IOException e){
e.printStackTrace();
}
}
When ran, it shows in the console that it is pointing to the correct file, but claims nothing exists there. I've checked, and the file is completely intact and in existence. What could be going wrong here?
You should not get a resource like that. You can use
BufferedReader reader = new BufferedReader(new InputStreamReader(
getClass().getResourceAsStream("/worlds/world1.txt")
));
Also, be careful when you package your application if you develop it inside an IDE, otherwise you'll run into common CLASSPATH troubles
File path for embedded resources is calculated from the package root folder. Assuming that src folder is the root package folder, make sure, that world1.txt file is located at src/worlds/ folder and full path is src/worlds/world1.txt
Second point, use the following code to obtain embedded file reader object:
// we do not need this line anymore
// File file = new File(getClass().getResource("/worlds/world1.txt").toString());
// use this approach
BufferedReader reader = new BufferedReader(
new InputStreamReader(
getClass().getResourceAsStream("/worlds/world1.txt"),
Charset.forName("UTF-8")));
You haven't indicated where your file lives.
getClass().getResource is used to locate a resource/file on your classpath; the resource may be packaged in your jar, for example. In this case, you can't open it as a File; see Raffaele's response.
If you want to locate the resource/file on the file system, then create the File object directly without getResource():
new File("/worlds/world1.txt")
I was using Netbeans and I was getting similar results. When I defined the file Path from the C drive and ran my code it stated: Access has been denied.
The following code ran fine, just back track your file location to the source (src) file.
//EXAMPLE FILE PATH
String filePath = "src\\solitaire\\key.data";
try {
BufferedReader lineReader = new BufferedReader(new FileReader(filePath));
String lineText = null;
while ((lineText = lineReader.readLine()) != null) {
hand.add(lineText);
System.out.println(lineText); // Test print of the lines
}
lineReader.close(); // Closes the bufferReader
System.out.print(hand); // Test print of the Array list
} catch(IOException ex) {
System.out.println(ex);
}
public class Cww {
static List<String> readFile(String filename) {
List<String> records = new ArrayList<String>();
try {
BufferedReader reader = new BufferedReader(new FileReader(filename));
String line;
while((line = reader.readLine()) != null)
{
records.add(line);
}
reader.close();
return records;
} catch(Exception e) {
System.out.println(e);
return null;
}
}
and my main:
readFile("DirList.java");
File file = new File("DirList.java");
System.out.println(file.getCanonicalPath());
// CLASSPATH: .;..;J:\Programowanie\eclipse workspace\tij;C:\Program Files\Java\jre7\lib\ext\QTJava.zip
output: java.io.FileNotFoundException: DirList.java (Nie można odnaleźć określonego pliku)
J:\Programowanie\eclipse workspace\Rozdzial 18 cwiczenia\DirList.java
file.getCanonicalPath() shows that jvm search for my file where it really is, but my fileRead method is still giving me error,
Do I need to include every project folder in my classpath to read files from them ?
Thanks in advance
The File constructor argument is an absolute or relative filename. It will not use the classpath, the filename is - if not absolute - always relative to the current working directory.
FileReader(filename) will open a "DirList.java" in the directory from where your java code was executed (relative path). It is not related to the CLASSPATH in any way.