Asked  7 Months ago    Answers:  5   Viewed   58 times

I am trying to get a path to a Resource but I have had no luck.

This works (both in IDE and with the JAR) but this way I can't get a path to a file, only the file contents:

ClassLoader classLoader = getClass().getClassLoader();
PrintInputStream(classLoader.getResourceAsStream("config/netclient.p"));

If I do this:

ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("config/netclient.p").getFile());

The result is: java.io.FileNotFoundException: file:/path/to/jarfile/bot.jar!/config/netclient.p (No such file or directory)

Is there a way to get a path to a resource file?

 Answers

95

This is deliberate. The contents of the "file" may not be available as a file. Remember you are dealing with classes and resources that may be part of a JAR file or other kind of resource. The classloader does not have to provide a file handle to the resource, for example the jar file may not have been expanded into individual files in the file system.

Anything you can do by getting a java.io.File could be done by copying the stream out into a temporary file and doing the same, if a java.io.File is absolutely necessary.

Tuesday, June 1, 2021
 
treeface
answered 7 Months ago
43
proc = Runtime.getRuntime().exec(cmd, null, fwrkDir);

should be

proc = Runtime.getRuntime().exec(cmd, "PATH=$PATH:/android-sdk-linux_x86/platform-tools", fwrkDir);
Saturday, July 31, 2021
 
Ben
answered 5 Months ago
Ben
40

Why is a file which is used as part of your application not in the same folder as the application? It sounds to me like you should set the properties on that file to copy to the output folder when you do a build.

Doing that will make sure your file is in the bindebug folder.

EDIT: either that or you should be placing your files in one of the special folders, app data or my documents spring to mind.

Sunday, October 10, 2021
 
akosch
answered 2 Months ago
91

For future viewers, the answer turned out to be very simple: the instructions for maven at the getting started with JavaFX are with intellij and maven (non-module version), as found here are slightly incorrect.

The instructions are as follows:

You can open the Maven Projects window and click on HelloFX -> Plugins -> compiler -> compiler:compile to compile the project, and click on HelloFX -> Plugins -> javafx -> javafx:run to execute the project.

The key part that is wrong here is that if you are using a project that uses static resources - like the FXML files in the HelloFX project - then compiling only using compiler:compile will not copy these files into the targetclasses directory.

This is a subtle mistake in the guide - presumably because if you build from command line nothing will be wrong - using mvn clean javafx:run will perform all the steps in between. Therefore, the instructions need to be to run compiler:compile and resources:resources for the thing to work in Intellij.

Alternatively, the guide could be changed to say just run javafx:compile or run the lifecycle phase called package in intellij, and then run javafx:run.

Wednesday, October 20, 2021
 
Hunex
answered 2 Months ago
63

Essentially the path is the index expressed in base size, where the latter is the maximum array size of the division. For example, 41 in base 5 is 131. Hence [1, 3, 1]. I think you mistakenly prefixed this with an additional 0 (just try console.log(result[1][3][1]) in your snippet).

Now, for lower indexes, you would need to prepad one or more zeroes so the path length is always the same for a given tree. The number of digits you need depends on the depth of the tree, which is determined by the largest index in the data. In your example, your data has a size of 100, so largest index is 99. 99 in base 5 is still 3 digits. So any path should have 3 digits in this case.

Remark about your implementation

The divide function currently does not produce the correct result when the data size is smaller than the chunk size. In that case it should just return the original array, but your code still wraps it in another array.

The fix is to make the size check at the start:

if (data.length <= size) return data;

Implementation

// Get path. Note that the actual tree is not needed; just the data size and chunk size
function getPath(chunkSize, dataSize, index) {
    if (index >= dataSize) throw new Error("index out of range");
    // Take logarithm, base chunkSize, from the highest possible index (i.e. dataSize - 1)
    let depth = Math.floor(Math.log(dataSize - 1) / Math.log(chunkSize)) + 1;
    let path = [];
    for (let i = 0; i < depth; i++) {
        // get each "digit" of the index when represented in base-chunkSize
        path.push(index % chunkSize);
        index = Math.floor(index / chunkSize);
    }
    return path.reverse();
}

let path = getPath(5, 100, 41);
console.log("path", path);

// Create the tree and extract that number at that index:
const data = [
 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
 1, 2, 3, 4, 5, 6, 7, 8, 9, 0
]

// I moved the base case detection first, so it works correctly 
//   for trees that are just the original array.
function divide(data, size) {
    if (data.length <= size) return data;
    const result = [];
    for (let i = 0; i < data.length; i += size) {
        result.push(data.slice(i, i + size))
    }
    return divide(result, size);
}

const tree = divide(data, 5);

// Now get the value using the path we got
let drill = tree;
while (path.length) {
    drill = drill[path.shift()];
}
console.log("value at path", drill);
Wednesday, December 8, 2021
 
JZ.
answered 1 Day ago
JZ.
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share