Gradle project and resources folder and logical root for creating files - java

I have a problem understanding how Intellij is working with a Gradle project and the resources folder.
I have created a default Gradle project its created a module 'group', and a module when looking in the module group the src/main/resources folder shows as a 'resource folder' (however it doesn't in the stand-alone module, where groovy/java/resources are all grey).
So that sort out seems to work when compiling code generally.
I tried however to create a file in Groovy script like this
File newFile = new File ("resources/temp.txt")
def fpath = newFile.toURL()
if (!newFile.exists()) {
println "creating new $fpath file "
newFile.createNewFile()
}
However run you run this it fails at bit like this
creating new file:/D:/Intellij - Azure/quickstart-java/graph/src/main/groovy/playpen/resources/temp.txt file
Caught: java.io.IOException: The system cannot find the path specified
java.io.IOException: The system cannot find the path specified
at java_io_File$createNewFile$1.call(Unknown Source)
at playpen.TinkerPop-Example.run(TinkerPop-Example.groovy:47)
The File seems to have relative root .../src/main/groovy/playpen which is where my script is. there is no src/main/groovy/playpen/resources/ so it fails
if a use File("/resources/temp.txt") and look at the URL it shows asD:\resources\temp.txt` defaulting to same drive as where the script is defined.
If you remove the resources prefix - the file gets created in playpen - again assumed root is same as the source program script.
What I want is to read a file from the 'resources' folder but unless I go to absolute file paths it just ignores the 'resources' folder and only looks in the Groovy source folders.
So for example if I copy the temp.txt into the resources folder and run this
File newFile = new File ("temp.txt")
def fpath = newFile.toURL()
if (!newFile.exists()) {
println "creating new $fpath file "
newFile.createNewFile()
} else {
println "reading file at $fpath"
}
it just creates a new temp.txt in the playpen package where the script runs and doesn't see a copy from 'resources' folder.
So what format of 'file name' do I use so that the 'resources' folder is naturally used to resolve file names - without having to use absolute file names?
Equally if want to create a File programmatically and save that in the 'resources' folder where the script runs from src/main/groovy/playpen, what's the path name that puts it in the correct location.
I'm missing something basic here and can't figure out how to read/or write from the resources folder.

ended up with brute force and ignorance on this one - someone may have a 'smarter'answer, but this one appears to be working. Slightly tweaked some code i got working.
I'm using groovy here rather than java (just less boilerplate noise), and nice File groovy methods
steps -
(1)first locate root of your IDE/project using System.getProperty("user.dir")
(2) get the current resource file for 'this' - the class you run from ide
(3) see if the resource is in $root/out/test/.. dir - it so its a test else its your normal code.
(4) set resourcePath now to correct 'location' either in src/main/resources or src/test/resources/ - then build rest of file from this stub
(5) check if file exists - if so delete and rewrite this (you can make this cleverer)
(6) create file and fill its contents
job done this file should now appear where you expect it. Happy to take cleverer ways to get do this - but for anyone else stuck this seems to do the trick
void exportToFile (dir=null, fileName=null) {
boolean isTest = false
String root = System.getProperty("user.dir")
URL url = this.getClass().getResource("/")
File loc = new File(url.toURI())
String canPath = loc.getCanonicalPath()
String stem = "$root${File.separatorChar}out${File.separatorChar}test"
if (canPath.contains(stem))
isTest = true
String resourcesPath
if (isTest)
resourcesPath = "$root${File.separatorChar}src${File.separatorChar}test${File.separatorChar}resources"
else
resourcesPath = "$root${File.separatorChar}src${File.separatorChar}main${File.separatorChar}resources"
String procDir = dir ?: "some-dir-string"
if (procDir.endsWith("$File.separatorChar"))
procDir = procDir - "$File.separatorChar"
String procFileName = fileName ?: "somedefaultname"
String completeFileName
File exportFile = "$resourcesPath${File.separatorChar}$procDir${File.separatorChar}${procFileName}"
exportFile = new File(completeFileName)
println "path: $procDir, file:$procFileName, full: $completeFileName"
exportFile.with {
if (exists())
delete()
createNewFile()
text = toString()
}
}

Related

right way to make a jar file from javafx application

I have a javafx project, which contains multiple paths for images and text files :
private Image imgMan = new Image(getClass().getResource("../man.gif").toExternalForm());
FileHelper.resetScores("./bin/application/MAP/BestScores.txt");
...
When i launch from eclipse, it work normally, and access to images and files without any problem.
But when i try to export my project to a jar file, it export correctly, but it don't launch !
I try to launch it from cmd, the trace of stack said that he don't know the paths...
Caused by: java.lang.NullPointerException
at application.Client.(Client.java:31)
(line 31 in my code refer to the first line of code given in the question)
I try to create a resource folder and put all files into it, but no result.
So what is the best way to make it ?
where must i create the resource folder ?
and how to access the files into it from the code ?
Thank you
There are several thing you should check:
verify the path in your jar against the class you are looking. Your image must be there.
verify you have successfully loaded a resource because using it, eg: check if getResource returns null.
For the first point, it depends on how you build your jar:
Eclipse will by default copy class file and resources to bin unless you use m2e. If you use the Extract runnable JAR (from File > Export menu), it may ignore some resources.
If you use Maven then your images must be in src/main/resources by default.
For the second point, you should use a method that should check the resource exists before delegating to Image. While it won't change your core problem, you would have a less subtile error:
static javafx.scene.image.Image loadImage(Class<?> source, String path) {
final InputStream is = source.getResourceAsStream(path);
if (null == is) {
throw new IllegalStateException("Could not load image from " + source + " path: " + path);
}
try (is) { // Java 9 -> you may want to use InputStream is2 = is
return new javafx.scene.image.Image(is); // use is2 for Java < 9
}
}
You should also try with an absolute path (from the root of the jar, or your src/main/resources if you use maven):
Image image = loadImage(this.getClass(), "/images/man.gif");

how to get full path of the current file including the src file in java

I have a file dateTesting.java . the path's directory is as follows: D:\workspace\Project1\src\dateTesting.java . I want the full path of this file as "D:\workspace\Project1\src" itself but when I use any of the following code, i get only "D:\workspace\Project1" . the src part is not coming.
System.out.println(System.getProperty("user.dir"));
File dir2 = new File(".");
System.out.println(dir2.getCanonicalPath().toString());
System.out.println(dir2.getAbsolutePath());
How can I get the full path as "D:\workspace\Project1\src" ? I'm using eclipse ide 3.5
Thank you
dateTesting.java is a Java source file which is not available after compilation to bytecode. The source directory it was in is not available, too.
dir2 is the File of the directory you execute the .class file in. It seams that this happens to be D:\workspace\Project1 but you can't rely on this.
Your dir2 points to working directory (new File(".")). You can't get the location of your sources this way. Your file could sit inside the package (e.g. your.company.date.dateTesting). You should just manually concat the "src" to current working directory and then replace file package dots (.) with File.pathSeparator. In that way you will build the full path to your file.
String fullFilePath = "H:\\Shared\\Testing\\abcd.bmp";
File file = new File(fullFilePath);
String filePath = file.getAbsolutePath().substring(0,fullFilePath.lastIndexOf(File.separator));
System.out.println(filePath);
Output:
H:\Shared\Testing
If you are doing this to try to read a file from the classpath, then check out this answer:
How to really read text file from classpath in Java
Essentially you can do this
InputStream in = this.getClass().getClassLoader()
.getResourceAsStream("SomeTextFile.txt");
Otherwise, if you have some other requirement, one option is to pass through the src directory as a JVM arg when the application begins and then just read it back.
/** The actual file running */
public static final File JAR_FILE = new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath();
/** The path to the main folder where the file .jar is run */
public static final String BASE_DIRECTORY = (JAR_FILE != null ? JAR_FILE.getAbsolutePath().replace(JAR_FILE.getName(), "") : "notFound");
This will work for you both in normal java execution and jar execution. This is the solution I am using in my project.

How to get absolute path to file in /resources folder of your project

Assume standard maven setup.
Say in your resources folder you have a file abc.
In Java, how can I get absolute path to the file please?
The proper way that actually works:
URL resource = YourClass.class.getResource("abc");
Paths.get(resource.toURI()).toFile();
It doesn't matter now where the file in the classpath physically is, it will be found as long as the resource is actually a file and not a JAR entry.
(The seemingly obvious new File(resource.getPath()) doesn't work for all paths! The path is still URL-encoded!)
You can use ClassLoader.getResource method to get the correct resource.
URL res = getClass().getClassLoader().getResource("abc.txt");
File file = Paths.get(res.toURI()).toFile();
String absolutePath = file.getAbsolutePath();
OR
Although this may not work all the time, a simpler solution -
You can create a File object and use getAbsolutePath method:
File file = new File("resources/abc.txt");
String absolutePath = file.getAbsolutePath();
You need to specifie path started from /
URL resource = YourClass.class.getResource("/abc");
Paths.get(resource.toURI()).toFile();
Create the classLoader instance of the class you need, then you can access the files or resources easily.
now you access path using getPath() method of that class.
ClassLoader classLoader = getClass().getClassLoader();
String path = classLoader.getResource("chromedriver.exe").getPath();
System.out.println(path);
There are two problems on our way to the absolute path:
The placement found will be not where the source files lie, but
where the class is saved. And the resource folder almost surely will lie somewhere in
the source folder of the project.
The same functions for retrieving the resource work differently if the class runs in a plugin or in a package directly in the workspace.
The following code will give us all useful paths:
URL localPackage = this.getClass().getResource("");
URL urlLoader = YourClassName.class.getProtectionDomain().getCodeSource().getLocation();
String localDir = localPackage.getPath();
String loaderDir = urlLoader.getPath();
System.out.printf("loaderDir = %s\n localDir = %s\n", loaderDir, localDir);
Here both functions that can be used for localization of the resource folder are researched. As for class, it can be got in either way, statically or dynamically.
If the project is not in the plugin, the code if run in JUnit, will print:
loaderDir = /C:.../ws/source.dir/target/test-classes/
localDir = /C:.../ws/source.dir/target/test-classes/package/
So, to get to src/rest/resources we should go up and down the file tree. Both methods can be used. Notice, we can't use getResource(resourceFolderName), for that folder is not in the target folder. Nobody puts resources in the created folders, I hope.
If the class is in the package that is in the plugin, the output of the same test will be:
loaderDir = /C:.../ws/plugin/bin/
localDir = /C:.../ws/plugin/bin/package/
So, again we should go up and down the folder tree.
The most interesting is the case when the package is launched in the plugin. As JUnit plugin test, for our example. The output is:
loaderDir = /C:.../ws/plugin/
localDir = /package/
Here we can get the absolute path only combining the results of both functions. And it is not enough. Between them we should put the local path of the place where the classes packages are, relatively to the plugin folder. Probably, you will have to insert something as src or src/test/resource here.
You can insert the code into yours and see the paths that you have.
To return a file or filepath
URL resource = YourClass.class.getResource("abc");
File file = Paths.get(resource.toURI()).toFile(); // return a file
String filepath = Paths.get(resource.toURI()).toFile().getAbsolutePath(); // return file path

Specifying a relative path in File in Java

I'm uploading images using Spring and Hibernate. I'm saving images on the server as follows.
File savedFile = new File("E:/Project/SpringHibernet/MultiplexTicketBooking/web/images/" + itemName);
item.write(savedFile);
Where itemName is the image file name after parsing the request (enctype="multipart/form-data"). I however need to mention the relative path in the constructor of File. Something like the one shown below.
File savedFile = new File("MultiplexTicketBooking/web/images/" + itemName);
item.write(savedFile);
But it doesn't work throwing the FileNotFoundException. Is there a way to specify a relative path with File in Java?
Try printing the working directory from your program.
String curDir = System.getProperty("user.dir");
Gets you that directory. Then check if the directories MultiplexTicketBooking/web/images/ exist in that directory.
Can't count the number of times I've been mistaken about my current dir and spent some time looking for a file I wrote to...
It seems the server should offer functionality as might be seen in the methods getContextPath() or getRealPath(String). It would be common to build paths based on those types of server related and reproducible paths. Do not use something like user.dir which makes almost no sense in a server.
Update
ServletContext sc=request.getSession().getServletContext();
File savedFile = new File(sc.getRealPath("images")+"\\" + itemName);
Rather than use "\\" I'd tend to replace that with the following which will cause the correct file separator to be used for each platform. Retain cross-platform compatibility for when the client decides to swap the MS/ISS based server out for a Linux/Tomcat stack. ;)
File savedFile = new File(sc.getRealPath("images"), itemName); //note the ','
See File(String,String) for details.
You could get the path of your project using the following -
File file = new File("");
System.out.println("" + file.getAbsolutePath());
So you could have a constants or a properties file where you could define your path which is MultiplexTicketBooking/web/images/ after the relative path.
You could append your path with the path you get from file.getAbsolutePath() and that will be the real path of the file. - file.getAbsolutePath() + MultiplexTicketBooking/web/images/.
Make sure the folders after the Project path i.e. MultiplexTicketBooking/web/images/ exist.
You can specify the path both absolute and relative with File. The FileNotFoundException can be thrown because the folder might be there. Try using the mkdirs() method first in to create the folder structure you need in order to save your file where you're trying to save it.

Locating default root folder for an Eclipse project

I am reading a file as follows:
File imgLoc = new File("Player.gif");
BufferedImage image = null;
try {
image = ImageIO.read(imgLoc);
}
catch(Exception ex)
{
System.out.println("Image read error");
System.exit(1);
}
return image;
I do not know where to place my file to make the Eclipse IDE, and my project can detect it when I run my code.
Is there a better way of creating a BufferedImage from an image file stored in your project directory?
Take a look in the comments for Class.getResource and Class.getResourceAsStream. These are probably what you really want to use as they will work whether you are running from within the directory of an Eclipse project, or from a JAR file after you package everything up.
You use them along the lines of:
InputStream in = MyClass.class.getResourceAsStream("Player.gif");
In this case, Java would look for the file "Player.gif" next to the MyClass.class file. That is, if the full package/class name is "com.package.MyClass", then Java will look for a file in "[project]/bin/com/package/Player.gif". The comments for getResourceAsStream indicate that if you lead with a slash, i.e. "/Player.gif", then it'll look in the root (i.e. the "bin" directory).
Note that you can drop the file in the "src" directory and Eclipse will automatically copy it to the "bin" directory at build time.
In the run dialog you can choose the directory. The default is the project root.
From my experience it seems to be the containing projects directory by default, but there is a simple way to find out:
System.out.println(new File(".").getAbsolutePath());
Are you trying to write a plugin for Eclipse or is it a regular project?
In the latter case, wouldn't that depend on where the program is installed and executed in the end?
While trying it out and running it from Eclipse, I'd guess that it would find the file in the project workspace. You should be able to find that out by opening the properties dialog for the project, and looking under the Resource entry.
Also, you can add resources to a project by using the Import menu option.
The default root folder for any Eclipse project is also a relative path of that application.
Below are steps I used for my Eclipse 4.8.0 and Java 1.8 project.
I - Place your file you want to interact with along the BIN and SRS folders of your project and not in one of those folders.
II - Implement below code in your main() method.
public static void main(String [] args) throws IOException {
FileReader myFileReader;
BufferedReader myReaderHelper;
try {
String localDir = System.getProperty("user.dir");
myFileReader = new FileReader(localDir + "\\yourFile.fileExtension");
myReaderHelper = new BufferedReader(myFileReader);
if (myReaderHelper.readLine() != null) {
StringTokenizer myTokens =
new StringTokenizer((String)myReaderHelper.readLine(), "," );
System.out.println(myTokens.nextToken().toString()); // - reading first item
}
} catch (FileNotFoundException myFileException) {
myFileException.printStackTrace(); } } // End of main()
III - Implement a loop to iterate through elements of your file if your logic requires this.

Categories