How to output text to a file in resource folder Maven

csv, java, maven

Solution

You can output text to a file in the `resources` folder, but the process is a bit tedious.

- Tell Maven to write the location of your `resources` folder into a file

- Read the location of your `resources` folder in Java

- Use that location to write your file to

Notes

Why bother specifying the location of your `resources` folder file? Isn't it `src/main/resources` always? Well no, if you have a nested module structure like

rootModule   
├─ childModule1   
│  └─ src    
│     └─ main    
│        └─ resources    
└─ childModule2 
   └─ ...  

then the relative path `src/main/resources` resolves to `parentModule/src/main/resources` which does not exist.

- Once you write the file to the `resources` folder, it will not be accessible through `Class.getResource()`. `Class.getResource()` provides you with read access to files located in your classpath. The files located in your `resources` folder are "copied" to your binary output folder (read classpath) during "compilation". In order to access your newly created resource file with the help of `Class.getResource()`, you will have to recompile & restart the application. However, you can still access it by the location you used for writing the file.

Guide

- add `RESOURCE_PATH` property to the Maven pom, and tell Maven to compile properties found in resource files

- add an utility file `src/main/resources/RESOURCE_PATH`, which only contains the `RESOURCE_PATH` property

- extract the `RESOURCE_PATH` property from the utility file in Java

- rebuild the project if needed (e.g. if file/folder structure changes)

POM

<project>
    ...
    <properties>
        <RESOURCE_PATH>${project.basedir}/src/main/resources</RESOURCE_PATH>
    </properties>
    ...
    <build>
        ...
        <resources>
            <resource>
                <directory>${RESOURCE_PATH}</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
        ....
    </build>
    ...
</project>

Utility file (`src/main/resources/RESOURCE_PATH`)

${RESOURCE_PATH}

Java

/**
 * Reads the relative path to the resource directory from the <code>RESOURCE_PATH</code> file located in
 * <code>src/main/resources</code>
 * @return the relative path to the <code>resources</code> in the file system, or
 *         <code>null</code> if there was an error
 */
private static String getResourcePath() {
    try {
        URI resourcePathFile = System.class.getResource("/RESOURCE_PATH").toURI();
        String resourcePath = Files.readAllLines(Paths.get(resourcePathFile)).get(0);
        URI rootURI = new File("").toURI();
        URI resourceURI = new File(resourcePath).toURI();
        URI relativeResourceURI = rootURI.relativize(resourceURI);
        return relativeResourceURI.getPath();
    } catch (Exception e) {
        return null;
    }
}

public static void main(String[] args) throws URISyntaxException, IOException {
    File file = new File(getResourcePath() + "/abc.txt");
    // write something to file here
    System.out.println(file.lastModified());
}

I hope that works. Maybe you need maven resources:resources plugin and do `mvn generate-resources process-resources`

Problem

Here is the structure of my maven project: main and test folders are under src folder, java and resources folders are under main folder, in the resources folder, there is a csv file ready for reading. ``` src --main |-- java |-- resources |-- test.csv test ``` Currently, I am trying to overwrite the test.csv file using supercsv library. I know that `public CsvMapWriter(Writer writer, CsvPreference preference)` method is helpful on that. So, I am trying to use OutputStreamWriter, but how to access that file like using: ``` InputStreamReader reader = new InputStreamReader(getClass().getClassLoader().getResourceAsStream("acacia_implexa.csv")); mapReader = new CsvMapReader(reader, CsvPreference.STANDARD_PREFERENCE); ```

Original source

Related problems