I have been happily using JUnit to run my tests and everything has been fine.
However, I now need to use Maven but for some reason it cannot find any of my resource files.
The files are in the expected place: src/main/resources
I am using the following code to try to read a file:
public Map<String, String> readCsv(String filename) {
Map<String, String> headersAsMap;
CSVDataManipulator csvDataManipulator = new CSVDataManipulator();
ClassLoader classLoader = getClass().getClassLoader();
String wrkbook = new File(classLoader.getResource(filename).getFile()).toString();
headersAsMap = csvDataManipulator.getAllRecordsAsMap(wrkbook);
return headersAsMap;
}
However, try as I might it cannot find the file.
I've tried lots of different code and tried moving the files to different locations but I cannot get Maven to find my resource files.
Any help would be greatly appreciated!
Thanks
To my understanding classLoader.getResource(..) expects the file to be in a folder structure matching the package of the class. So if the package of your class is com.matt.stuff, then you'll have to put the csv file in src/main/resources/com/matt/stuff.
Or you could just use this to grab your csv file:
private static String readFile(String fileName) throws IOException {
//filename can be src/main/resources/my-csv.csv
return new String(Files.readAllBytes(Paths.get(fileName)));
}
A File is indeed a file on the file system. For a resource which might be a file zipped in a jar, and has a path on the class path, you need something else.
Traditionally one would use a more general InputStream instead of a File.
InputStream in = getClass().getResourceAsStream("/.../x.csv"); // Path on the class path
With the new class Path, more general than File, you can deal with several (virtual) file systems:
URL url = getClass().getResource("/.../x.csv"); // Path on the class path
Path path = Paths.get(url.toURI());
Files.copy(path, Paths.get("..."));
With a bit of luck your CSVManipulator should besides being parametrized with a File, also with an InputStream or Reader (new InputStreamReader(in, "UTF-8"))
Here's my file structure of a Maven project built from the quick-start-archetype, with comons-io added as a dependency:
src
src/main
src/main/java
src/main/java/com
src/main/java/com/essexboy
src/main/java/com/essexboy/App.java
src/main/resources
src/main/resources/dir1
src/main/resources/dir1/test.txt
src/main/resources/dir2
src/main/resources/dir2/test.txt
src/main/resources/test.txt
src/test
src/test/java
src/test/java/com
src/test/java/com/essexboy
src/test/java/com/essexboy/AppTest.java
Here's my test
public class AppTest {
#Test
public void shouldAnswerWithTrue() throws Exception {
StringWriter writer = new StringWriter();
IOUtils.copy(getClass().getResourceAsStream("/test.txt"), writer, Charset.defaultCharset());
assertEquals("from root", writer.toString().trim());
writer = new StringWriter();
IOUtils.copy(getClass().getResourceAsStream("/dir1/test.txt"), writer, Charset.defaultCharset());
assertEquals("from dir1", writer.toString().trim());
writer = new StringWriter();
IOUtils.copy(getClass().getResourceAsStream("/dir2/test.txt"), writer, Charset.defaultCharset());
assertEquals("from dir2", writer.toString().trim());
}
}
Related
I created folder src/test/resources/ in root project directory, and inside this I added a file in folder jsons as jsons/server_request.json.
Now I am trying to read this file by calling a the static function in CommonTestUtilityclass given as:
public class CommonTestUtility {
public static String getFileAsString(String fileName) throws IOException {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
File file = new File(classLoader.getResource(fileName).getFile());
String content = new String(Files.readAllBytes(file.toPath()));
return content;
}
}
Now while calling this function as
class ServerTest {
#Test
void test_loadResource() {
String content = CommonTestUtility.getFileAsString("jsons/server_request.json");
}
}
, It's giving me the error as:
CommonTestUtility - Cannot invoke "java.net.URL.getFile()" because the return value of "java.lang.ClassLoader.getResource(String)" is null.
I tried to include the src/test/resources/ in the run configuration
of Junit ServerTest.java, but still it's not able to find out the
resource
How to resolve this issue?
https://mkyong.com/java/java-read-a-file-from-resources-folder/
This above link might be helpful.
The getResource() method return an URI you need to change
.getFile() function to. toURI().
Simple code
private File getFileFromResource(String fileName) throws URISyntaxException{
ClassLoader classLoader = getClass().getClassLoader();
URL resource = classLoader.getResource(fileName);
if (resource == null) {
throw new IllegalArgumentException("file not found! " + fileName);
} else {
// failed if files have whitespaces or special characters
//return new File(resource.getFile());
return new File(resource.toURI());
}
}
I recreated the same scenario you describe and your code works for me.
Could you double-check that your project looks like mine below? If so, I suspect it might be something with your environment.
I'm trying to unmarshal my xml file:
public Object convertFromXMLToObject(String xmlfile) throws IOException {
FileInputStream is = null;
File file = new File(String.valueOf(this.getClass().getResource("xmlToParse/companies.xml")));
try {
is = new FileInputStream(file);
return getUnmarshaller().unmarshal(new StreamSource(is));
} finally {
if (is != null) {
is.close();
}
}
}
But I get this errors:
java.io.FileNotFoundException: null (No such file or directory)
Here is my structure:
Why I can't get files from resources folder? Thanks.
Update.
After refactoring,
URL url = this.getClass().getResource("/xmlToParse/companies.xml");
File file = new File(url.getPath());
I can see an error more clearly:
java.io.FileNotFoundException: /content/ROOT.war/WEB-INF/classes/xmlToParse/companies.xml (No such file or directory)
It tries to find WEB-INF/classes/
I have added folder there, but still get this error :(
I had the same problem trying to load some XML files into my test classes. If you use Spring, as one can suggest from your question, the easiest way is to use org.springframework.core.io.Resource - the one Raphael Roth already mentioned.
The code is really straight forward. Just declare a field of the type org.springframework.core.io.Resource and annotate it with org.springframework.beans.factory.annotation.Value - like that:
#Value(value = "classpath:xmlToParse/companies.xml")
private Resource companiesXml;
To obtain the needed InputStream, just call
companiesXml.getInputStream()
and you should be okay :)
But forgive me, I have to ask one thing: Why do you want to implement a XML parser with the help of Spring? There are plenty build in :) E.g. for web services there are very good solutions that marshall your XMLs into Java Objects and back...
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("fileName").getFile());
you are suppose to give an absolute path (so add a loading ´/´, where resource-folder is the root-folder):
public Object convertFromXMLToObject(String xmlfile) throws IOException {
FileInputStream is = null;
File file = new File(String.valueOf(this.getClass().getResource("/xmlToParse/companies.xml")));
try {
is = new FileInputStream(file);
return getUnmarshaller().unmarshal(new StreamSource(is));
} finally {
if (is != null) {
is.close();
}
}
}
In Eclipse, my directory structure is this:
-src
-com.xxx.yyy
- MyClass.java
-assets
- car.txt
MyClass.java looks like this :
public class MyClass {
private static String FILE_PATH = "../assets/car.txt";
public static void main(String[] args) {
try {
//FileNotFoundException
FileInputStream fis = new FileInputStream(new File(FILE_PATH));
}
...
}
}
I this by default, the classpath is src/, so I point to my car.txt file by ../assets/car.txt. But I get :
java.io.FileNotFoundException: ../assets/car.txt (No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
Why ?
Relative file paths a relative to the execution, assuming that the program is executed in the same location as the src and assets directory, then the path should be assets/car.txt
You can check the current execution location using System.out.println(new File(".").getCanonicalPath());
Whe you run the program it is compiled to the parent folder of the src folder as far as I know. You should better add the assets folder to your build path and access the file using getClass().getResource[AsStream]().
To add the folder do the following:
Right click on your project
Click Build Path
Choose Configure Build Path
Select Source
Click Add Folder...
Select your assets folder
Inside your code you can either call it with MyClass.class.getResource[AsStream]() or getClass().getResource[AsStream]().
getResource() returns an URL and getResourceAsStream() an InputStream. Both methods expect a path as parameter. Check the docs for more information.
Your path is incorrect
Since you are inside com.xxx.yyy, you are inside three folders. You need to get out of all of them.
So you can use, the relative path as
FILE_PATH = "../../../assets/car.txt";
As src is a source folder, all the contents come directly in the classpasth, you can also use
FILE_PATH = "assets/car.txt";
You are in second level in directory structure.
Try
FILE_PATH = "../../assets/car.txt";
Hope, this will help you...
package com.xxx.yyy;
import java.io.File;
import java.io.FileInputStream;
public class MyClass {
private static String FILE_PATH = "src/assets/car.txt";
public static void main(String[] args) {
try {
//FileNotFoundException
FileInputStream fis = new FileInputStream(new File(FILE_PATH));
}
catch (Exception e){
e.printStackTrace();
}
}
}
Ankit Lamba 's suggestion works: that's using String FILE_PATH = "assets/car.txt";
I have a FileInputStream in a class in the package com.nishu.ld28.utilities, and I want to access sound files in the folder Sounds, which is not in the com.nishu.ld28 package. I specify the path for loading like so:
"sounds/merry_xmas.wav"
And then try to load it like this:
new BufferedInputStream(new FileInputStream(path))
When I export the jar, the command line prompt that I run it through says it can't find the file. I know how to access the files when I am running the program in Eclipse, but I can't figure out how to point the FileInputStream to the Sounds folder when I export it.
Edit: As requested, here's my code:
public void loadSound(String path) {
WaveData data = null;
data = WaveData.create(GameSound.class.getClassLoader().getResourceAsStream(path));
int buffer = alGenBuffers();
alBufferData(buffer, data.format, data.data, data.samplerate);
data.dispose();
source = alGenSources();
alSourcei(source, AL_BUFFER, buffer);
}
WaveData accepts an InputStream or other types of IO.
You don't need a FileInputStream, because you aren't reading from the filesystem. Use the InputStream returned by ClassLoader.getResourceAsStream(String res) or Class.getResourceAsStream(String res). So either
in = ClassLoader.getResourceAsStream("sounds/merry_xmas.wav");
or
in = getClass().getResourceAsStream("/sounds/merry_xmas.wav");
Note the leading slash in the second example.
I would put the com.nishu.ld28.utilities in the same package of your class , let's call it MyClass.
Your package:
Your code:
package com.nishu.ld28.utilities;
import java.io.InputStream;
public class MyClass {
public static void main(String[] args) {
InputStream is = MyClass.class.getResourceAsStream("sound/merry_xmas.wav");
System.out.format("is is null ? => %s", is==null);
}
}
Output
is is null ? => false
I have a properties file which is located under conf folder. conf folder is under the project root directory. I am using the following code.
public class PropertiesTest {
public static void main(String[] args) {
InputStream inputStream = PropertiesTest.class
.getResourceAsStream("/conf/sampleprop.conf");
Properties prop = new Properties();
try {
prop.load(inputStream);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(prop.getProperty("TEST"));
}
}
But I get nullpointer exception.
I have tried using
InputStream inputStream = PropertiesTest.class
.getResourceAsStream("./conf/sampleprop.conf");
and
InputStream inputStream = PropertiesTest.class
.getResourceAsStream("conf/sampleprop.conf");
But all result in nullpointer exception.
Can anyone please help.
Thanks in advance
Try to recover your working directory first:
String workingDir = System.getProperty("user.dir");
System.out.println("Current working dir: " + workingDir);
and then is simple:
Properties propertiesFile = new Properties();
propertiesFile.load(new FileInputStream(workingDir+ "/yourFilePath"));
String first= propertiesFile.getProperty("myprop.first");
Regards, fabio
The getResourceAsStream() method tries to locate and load the resource using the ClassLoader of the class it is called on. Ideally it can locate the files only the class folders .. Rather you could use FileInputStream with relative path.
EDIT
if the conf folder is under src, then you still be able to access with getResourceAsStream()
InputStream inputStream = Test.class
.getResourceAsStream("../conf/sampleprop.conf");
the path would be relative to the class from you invoke getRes.. method.
If not
try {
FileInputStream fis = new FileInputStream("conf/sampleprop.conf");
Properties prop = new Properties();
prop.load(fis);
System.out.println(prop.getProperty("TEST"));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
NOTE: this will only work if it is Stand alone application/in eclipse. This will not work if its web based (as the root will be Tomcat/bin, for eg)
I would suggest to copy the configuration file at designated place, then you can acess at ease. At certain extent 'System.getProperty("user.dir")' can be used if you are always copying the file 'tomcat` root or application root. But if the files to be used by external party, ideal to copy in a configurable folder (C:\appconf)
Your code works like a charm! But you might have to add the project root dir to your classpath.
If you work with Maven, place your configuration in src/main/resources/conf/sampleprop.conf
When invoking java directly add the project root dir with the java -classpath parameter. Something like:
java -classpath /my/classes/dir:/my/project/root/dir my.Main