I have the need to create an IFolder in an absolute location.
I usually have a class that does a "build" (or at least what I call a "build") for me in the workspace. The IFolder for the build-target-folder is returned by a method like this:
public IFolder getTargetFolder(IProject project){
return project.getFolder("build");
}
Now I created a subclass of this for the "deployment" (into a directory with absolute identifier). This subclass contains the same functionality but the getTargetfolder routine should be like this:
#Override
public IFolder getTargetFolder(IProject project){
IPath path = new Path("M:\\Path\\To\\My\\Deployment\\Directory\\");
IFolder target = project.getFolder(path);
return target;
}
However, I run into problems and I seem to not get a handle on the folder and an exception that says the folder (<ProjectRoot>/Path/To/My/Deployment/Directory) does not exist. How can I specify that this should not be a relative path?
The name given to project.getFolder() must be the name of a member folder (see the JavaDoc).
You cannot access a file or folder with the Resources API that lies outside of the workspace. If however the M:\\... path lies within a projects that is part of the workspace then you can resolve the folder through IWorkspaceRoot#getContainerForLocation()
For example:
IContainer container = project.getWorkspace().getRoot().getContainerForLocation( "M:\\..." );
The returned container can be either an IProject or an IFolder. But note that the returned container does not necessarily lies within the project.
Some more information can be found in Resources and the file system
Related
I am trying to load an image to use as an icon in my application. The appropriate method according to this tutorial is:
protected ImageIcon createImageIcon(String path, String description)
{
java.net.URL imgURL = getClass().getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL, description);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
So, I placed the location of the file, and passed it as a parameter to this function. This didn't work, i.e. imgURL was null. When I tried creating the ImageIcon by passing in the path explicitly:
ImageIcon icon = new ImageIcon(path,"My Icon Image");
It worked great! So the application can pick up the image from an explicitly defined path, but didn't pick up the image using getResources(). In both cases, the value of the path variable is the same. Why wouldn't it work? How are resources found by the class loader?
Thanks.
getClass().getResource(path) loads resources from the classpath, not from a filesystem path.
You can request a path in this format:
/package/path/to/the/resource.ext
Even the bytes for creating the classes in memory are found this way:
my.Class -> /my/Class.class
and getResource will give you a URL which can be used to retrieve an InputStream.
But... I'd recommend using directly getClass().getResourceAsStream(...) with the same argument, because it returns directly the InputStream and don't have to worry about creating a (probably complex) URL object that has to know how to create the InputStream.
In short: try using getResourceAsStream and some constructor of ImageIcon that uses an InputStream as an argument.
Classloaders
Be careful if your app has many classloaders. If you have a simple standalone application (no servers or complex things) you shouldn't worry. I don't think it's the case provided ImageIcon was capable of finding it.
Edit: classpath
getResource is—as mattb says—for loading resources from the classpath (from your .jar or classpath directory). If you are bundling an app it's nice to have altogether, so you could include the icon file inside the jar of your app and obtain it this way.
As a noobie I was confused by this until I realized that the so called "path" is the path relative to the MyClass.class file in the file system and not the MyClass.java file. My IDE copies the resources (like xx.jpg, xx.xml) to a directory local to the MyClass.class. For example, inside a pkg directory called "target/classes/pkg. The class-file location may be different for different IDE's and depending on how the build is structured for your application. You should first explore the file system and find the location of the MyClass.class file and the copied location of the associated resource you are seeking to extract. Then determine the path relative to the MyClass.class file and write that as a string value with "dots" and "slashes".
For example, here is how I make an app1.fxml file available to my javafx application where the relevant "MyClass.class" is implicitly "Main.class". The Main.java file is where this line of resource-calling code is contained. In my specific case the resources are copied to a location at the same level as the enclosing package folder. That is: /target/classes/pkg/Main.class and /target/classes/app1.fxml. So paraphrasing...the relative reference "../app1.fxml" is "start from Main.class, go up one directory level, now you can see the resource".
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("../app1.fxml"));
Note that in this relative-path string "../app1.fxml", the first two dots reference the directory enclosing Main.class and the single "." indicates a file extension to follow. After these details become second nature, you will forget why it was confusing.
getResource by example:
package szb.testGetResource;
public class TestGetResource {
private void testIt() {
System.out.println("test1: "+TestGetResource.class.getResource("test.css"));
System.out.println("test2: "+getClass().getResource("test.css"));
}
public static void main(String[] args) {
new TestGetResource().testIt();
}
}
output:
test1: file:/home/szb/projects/test/bin/szb/testGetResource/test.css
test2: file:/home/szb/projects/test/bin/szb/testGetResource/test.css
getResourceAsStream() look inside of your resource folder. So the fil shold be placed inside of the defined resource-folder
i.e if the file reside in /src/main/resources/properties --> then the path should be /properties/yourFilename.
getClass.getResourceAsStream(/properties/yourFilename)
For some reason I keep getting an NPE in a gradle javafx project.
My folder structure is very basic. I have a package with my java files in the main/java folder. I also have my resources in the main/resources folder. When I try to load image.png it gives me an NPE.
public static Image createImage(Object context, String url) {
Image m = null;
InputStream str = null;
URL _url = context.getClass().getResource(url);
try {
m = new Image(_url.getPath());
} catch (NullPointerException e) {
e.printStackTrace();
}
return m;
}
This is a helper class.
From the Scene I call: Image image = Helper.createImage(this, "image.png");
The absolute path to the image would be main/resources/images/image.png.
I checked every tutorial on the internet but I couldn't find any solution for this. I also tried it with the path to the image as parameter and also with an InputStream but it never worked.
Resources
The Class#getResource(String) and related API are used for locating resources relative to the class path and/or module path. When using Class to get a resource you can pass an absolute name or a relative name. An absolute name will locate the resource relative to the root of the class path/module path; an absolute name starts with a /. A relative name will locate the resource relative to the location of the Class; a relative name does not start with a leading /.
In a typical Maven/Gradle project structure, the src/main/java and src/main/resources are roots of the class path/module path. This means all resource names are relative to those directories. It's slightly more complicated than that because the files under those directories are moved to the target/build directory and it's that location that's put on the class path/module path, but for all intents and purposes consider the source directories as the root. There's a reason a get-resource API exists in the first place, to provide an application-location-independent way of obtaining resources.
Issues in Your Code
From your question I gather your project structure looks something like:
<project-dir>
|--src/
|--main/
|--java/
|--resources/
|--images/
|--image.png
And you're calling your method with an Object and a resource name of image.png. The problem here is that, since you're passing a relative name, the resource is located relative to the Class of the passed Object (i.e. context). I doubt your class is located in a package named images which means the resource will not be found relative to said class. You need to pass an absolute name: /images/image.png.
The other problem is your use of URL#getPath(). The URL you obtain from Class#getResource(String) will, if the resource were to be found, look something like this:
file:/path/to/gradle/project/build/resources/main/images/image.png
But the result of URL#getPath() will give you:
/path/to/gradle/project/build/resources/main/images/image.png
This causes a problem due to the way Image works. From the documentation:
All URLs supported by URL can be passed to the constructor. If the passed string is not a valid URL, but a path instead, the Image is searched on the classpath in that case.
Notice the second sentence. If the passed URL does not have a scheme then it's interpreted as a resource name and the Image will locate the image file relative to the classpath. In other words, since you're passing the value of URL#getPath() to the Image constructor it searches for the resource image.png in the package path.to.gradle.project.build.resources.main.images. That package does not exist. You should be passing the URL as-is to the Image constructor via URL#toString() or URL#toExternalForm().
Solution
If you're going to use the URL returned by Class#getResource(String) to load the Image then no matter what you need to use URL#toString() or URL#toExternalForm() instead of URL#getPath().
public static Image createImage(Object context, String resourceName) {
URL _url = context.getClass().getResource(resourceName);
return new Image(_url.toExternalForm());
}
Then you have at least two options:
Pass the absolute resource name (i.e. "/images/image.png") to your #createImage(Object,String) method since the image.png resource is not in the same package as the passed Object (i.e. context).
Move the resource to the same package as the class of the passed in Object (i.e. context). For instance, if the context object's class is com.foo.MyObject then place the resource under src/main/resources/com/foo and it will be in the same package as MyObject. This will allow you to continue passing the relative resource name.
Of course, as noted by the documentation of Image you can pass a scheme-less URL and it's interpreted as a resource name. In other words, you could do:
Image image = new Image("images/image.png");
And that should work. A note of caution, however: When using modules the above will only work if the resource-containing package is opens unconditionally or if the module itself is open.
Try using the path /images/image.png.
The resources always get referenced from the class root, in your case src/main/resources, so from there going to /images/image.png should be the correct path.
this is how I am passing the images in my application. ivSerialAssignmentLogo is a FXML element (ImageView).
ivSerialAssignmentLogo.setImage(new Image(getClass().getResourceAsStream("/img/serialAssignment.svg")));
In your case, you could use something like that
public static Image createImage(Object context, String url) {
Image m = null;
InputStream str = null;
URL _url = context.getClass().getResource("/images/" + url);
try {
m = new Image(_url.getPath());
} catch (NullPointerException e) {
e.printStackTrace();
}
return m;
}
I an new to Eclipse Plugin Development and I am trying to rename my linked file.
I have created a linked file in Eclipse as below:
IFile myLinkedFile = folder.getFile(originalFileName);
myLinkedFile.createLink(myabsolutePath, IResource.NONE, null);
This works like a charm.
However, now I would like to rename myLinkedFile without changing the name of the original File. Just like the behavior of pressing F2 or by the Rename from the context menu that appears on right clicking the liked file.
I am trying to achieve renaming using move()
originalFile.move(newPath, IResource.FORCE, null);
However it always throws
org.eclipse.core.internal.resources.ResourceException
...and complains about my newPath. Can someone tell me what is wrong in my approach and how do I do it right?
My original file is a text file located at C:/Temp/originalFile.txt. I would like to rename the file to newFile.txt in my workspace. The exception says invalid path. For the newPath I have specified as C:/Temp/newFile.txt
In the below example the original files is located in the resources folder of my project
Here I am creating a new folder called myTextFiles. This folder will contain the linked files.
After creating the linked files I am trying to rename the linked files.
IFolder folder = myCurrentProject.getFolder("myTextFiles");
folder.create(IResource.REPLACE, true, null);
IFile file = folder.getFile(absoluteLocation); //absolute location of folder containing images
file.createLink(absoluteLocation, IResource.REPLACE, null);
folder.refreshLocal(IResource.DEPTH_INFINITE, null);
String myNewFileName = "newFile.txt";
IFile myLinkedFile = folder.getFile(myNewFileName);
IPath newPath = new Path(myNewFileName);
IFile movedFile = folder.getFile(newFileName);
movedFile.createLink(newPath, IResource.NONE, null);
folder.refreshLocal(IResource.DEPTH_INFINITE, null);
You can only use move to move the resource to a new location in the Eclipse workspace.
The path you specify for move must be a path relative to the root of the Eclipse workspace or relative to the current resource location - often just a file name.
So
IPath newPath = new Path("/project/folder/newFile.txt");
or
IPath newPath = new Path("newFile.txt");
Paths starting with '/' are relative to the workspace root (known as a 'absolute' path), anything else is relative to the current resource folder.
Paths in the Eclipse workspace never use "C:/"
I'm working with Java 1.8. I'm trying to create a folder if not exists using this method:
private void createDirIfNotExists(String dirChemin) {
File file = new File(dirChemin);
if (!file.exists()) {
file.mkdirs();
}
}
This works when I give it the right path, for example this creates a folder if it doesn't exist
createDirIfNotExists("F:\\dir")
But when I write an incorrect path (or name), it didn't give me any thing even an error! for example :
createDirIfNotExists("F:\\..?§;>")
So I want to improve my method, so it can create the folder if it doesn't exist by making sure that my path is right, otherwise it should give me an error message.
mkdirs() also creates parent directories in the path this File represents.
javadocs for mkdirs():
Creates the directory named by this abstract pathname, including any
necessary but nonexistent parent directories. Note that if this
operation fails it may have succeeded in creating some of the
necessary parent directories.
javadocs for mkdir():
Creates the directory named by this abstract pathname.
Example:
File f = new File("non_existing_dir/someDir");
System.out.println(f.mkdir());
System.out.println(f.mkdirs());
will yield false for the first [and no dir will be created], and true for the second, and you will have created non_existing_dir/someDir
I have a unit test package in which I keep a few txt files. These get loaded via getClass().getResource(file); call and it works just fine. I added into the same folder a csv file, and if I supply its name as the parameter i.e. getClass().getResource("csvFile.csv"); I get null... any ideas why?
When you use
getClass().getResource("csvFile.csv");
it looks relative to the class.
When you use
getClass().getClassLoader().getResource("csvFile.csv");
it looks in the top level directories of your class path.
I suspect you want the second form.
From Class.getResource(String)
Before delegation, an absolute resource name is constructed from the given resource name using this algorithm:
If the name begins with a '/' ('\u002f'), then the absolute name of the resource is the portion of the name following the '/'.
Otherwise, the absolute name is of the following form:
modified_package_name/name
Where the modified_package_name is the package name of this object with '/' substituted for '.' ('\u002e').
As you can see the directory translation of the package name of the class is used.
For example, I have a maven project where the code is under src/main/java. My resources directory src/main/resources
I add csvFile.csv to my resources directory which will be copied to my class path.
public class B {
B() {
URL resource = getClass().getClassLoader().getResource("csvFile.csv");
System.out.println("Found "+resource);
}
public static void main(String... args) {
new B();
}
}
which prints
Found file:/C:/untitled/target/classes/csvFile.csv
This is in the area built by maven from the resources directory.
Have you tried getClass().getClassLoader().getResourceAsStream(file)
This in turn returns an inputstream which you can use to access the file