15

How can I save / load a file that is located where my classes are? I don't the physical path to that location before and I want dynamically to find that file.

I want to load an XML file and write and read to it and I am not sure how to address it.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Doron Sinai
  • 1,166
  • 3
  • 12
  • 28

6 Answers6

40

Use ClassLoader#getResource() or getResourceAsStream() to obtain them as URL or InputStream from the classpath.

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("com/example/file.ext");
// ...

Or if it is in the same package as the current class, you can also obtain it as follows:

InputStream input = getClass().getResourceAsStream("file.ext");
// ...

Saving is a story apart. This won't work if the file is located in a JAR file. If you can ensure that the file is expanded and is writable, then convert the URL from getResource() to File.

URL url = classLoader.getResource("com/example/file.ext");
File file = new File(url.toURI().getPath());
// ...

You can then construct a FileOutputStream with it.

Related questions:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 3
    `url.toURI()` - There will be `NullPointerException` if file doesn't exist. – naXa stands with Ukraine Oct 21 '14 at 12:44
  • 3
    @naXa: That's correct. Just check beforehand if `url` is not `null` in case you're unsure. It's not different for any other Java variable which you're attempting to access using period operator `.`. Every self-respected Java developer knows this. – BalusC Oct 21 '14 at 12:45
  • This answers how to update a file that exists on the classpath, but will not allow you to create a file due to `getResource` returning null. – ScrappyDev Jan 12 '17 at 18:09
  • The counterpart of using URI, is you have to capture `URISyntaxException`. – another Sep 18 '17 at 10:40
12

You can try the following provided your class is loaded from a filesystem.

String basePathOfClass = getClass()
   .getProtectionDomain().getCodeSource().getLocation().getFile();

To get a file in that path you can use

File file = new File(basePathOfClass, "filename.ext");
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 1
    Your code goes into the root of the project, so if you want to access a specific file in a package, just add (to your code): + "/" + fileName; – Zuenonentu Feb 25 '16 at 09:52
  • 1
    This worked to me, others not. I would add this to the answer: `File file = new File(basePathOfClass + "Filename.txt");` – another Sep 18 '17 at 10:38
8

new File(".").getAbsolutePath() + "relative/path/to/your/files";

user489041
  • 27,916
  • 55
  • 135
  • 204
  • It would be nice to comment why you give answers a minus 1 – user489041 Jan 17 '11 at 15:15
  • 7
    It's likely because this is basically dependent on the current working directory, not on the classpath. The working directory is not the classpath root per se and, even more, this is in no way controllable from inside the program. It depends fully on the way how you started the program, thus this is too error prone. – BalusC Jan 17 '11 at 15:21
  • Understandable, however it works good enough for me. But to each, their own. – user489041 Jan 17 '11 at 15:24
7

In the general case you cannot. Resources loaded from a classloader can be anything: files in directories, files embedded in jar files or even downloaded over the network.

gabuzo
  • 7,378
  • 4
  • 28
  • 36
  • 11
    I don't understand why this question is marked as right. – Rafael Ruiz Tabares Jun 01 '14 at 09:00
  • 1
    @RafaelRuizTabares Its a answer. – Ajinkya Jun 03 '14 at 13:04
  • I know @karna. But the question is why? Because I think it's a empty answer. Otherwise Baluc answer is more complete. – Rafael Ruiz Tabares Jun 03 '14 at 13:49
  • @RafaelRuizTabares That only OP can answer – Ajinkya Jun 03 '14 at 16:56
  • 2
    @RafaelRuizTabares totally agree with you that BalusC answer is more complete but I think I gave an answer which is that in the general case you cannot save to the classpath since it can be on any possible medium, most probably not supporting write operations. – gabuzo Jun 09 '14 at 18:38
  • The reason BalusC's answer is better is because it considers the concrete technical problem that the question poses, rather than the more abstract metatechnical question that is "what persistence layer is the classpath backed by?". The latter question may have some merits of its own, but it is not what is being asked here. – Chris Browne May 14 '18 at 09:14
5

This is an expansion on Peter's response:

If you want the file in the same classpath as the current class (Example: project/classes):

URI uri = this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI();
File file = new File(new File(uri), PROPERTIES_FILE);
FileOutputStream out = new FileOutputStream(createPropertiesFile(PROPERTIES_FILE));
prop.store(out, null);

If you want the file in a different classpath (Example: progect/test-classes), just replace this.getClass() with something like TestClass.class.

Read Properties from Classpath:

Properties prop = new Properties();

System.out.println("Resource: " + getClass().getClassLoader().getResource(PROPERTIES_FILE));
InputStream in = getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
if (in != null) {
    try {
        prop.load(in);
    } finally {
        in.close();
    }
}

Write Properties to Classpath:

Properties prop = new Properties();
prop.setProperty("Prop1", "a");
prop.setProperty("Prop2", "3");
prop.setProperty("Prop3", String.valueOf(false));

FileOutputStream out = null;
try {
    System.out.println("Resource: " + createPropertiesFile(PROPERTIES_FILE));
    out = new FileOutputStream(createPropertiesFile(PROPERTIES_FILE));
    prop.store(out, null);
} finally {
    if (out != null) out.close();
}

Create the File Object on the Classpath:

private File createPropertiesFile(String relativeFilePath) throws URISyntaxException {
    return new File(new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI()), relativeFilePath);
}
ScrappyDev
  • 2,307
  • 8
  • 40
  • 60
1

According to system properties documentation, you can access this as the "java.class.path" property:

string classPath = System.getProperty("java.class.path");
Wim Coenen
  • 66,094
  • 13
  • 157
  • 251
  • 2
    Won't be enough because it won't tell you from which part of the classpath the class is loaded from. – gabuzo Jan 17 '11 at 15:21