Java library function to find shadow file in different directory - java

I often have code where I loop over a directory (including subdirectories) and need to move / copy the file to a different directory. What I find tedious is the process of identifying where the file will go. I have often done that, usually like this:
File shadow = new File(sourceFile.getAbsolutePath()
.replace(
sourceFolder.getAbsolutePath(),
targetFolder.getAbsolutePath()
)
);
My question: is there a standard routine to do this or something similar in any major open source library? I didn't find one in Commons IO anyway...
I am not looking for complete move / copy solutions, I know tons of those. I just want the equivalent of the above code.
An Example, as requested:
Source folder:
src/main/resources
Target folder:
target/classes
Source file:
src/main/resources/com/mycompany/SomeFile.txt
Target file (the one I'm looking for):
target/classes/com/mycompany/SomeFile.txt
(I usually do stuff like this in a maven context, hence these folders but they could be non-maven folders, as well, the question has nothing to do with maven)

What you are looking for I have never found either but it will exist soon when JDK 7 (eventually) crawls out the door.
Path.relativize(Path) (Java 7 API)
For now I would stick to your current solution (or roll your own equivalent of the above).

Have you seen the org.apache.commons.io.FilenameUtils concat method? It takes a base directory (your target) and file-name to append. You would need to calculate the sourceFolder prefix ("src/main/resources".length()) and do a substring. Something like:
File shadow = new File(FilenameUtils.concat(targetFolder.getAbsolutePath(),
sourceFile.getAbsolutePath().substring(prefixLength));
Not much better than rolling you own though.
Apache's org.apache.commons.io.FileUtils also has functionality that you might use although I don't see a specific solution to your question:
FileUtils.moveFileToDirectory()
FileUtils.copyDirectory()
FileUtils.moveDirectory()
You could use copyDirectory with a FileFilter to choose which files to move over:
FileUtils.copyDirectory(File, File, FileFilter)

Related

Can't get resources from jar

In my project i need to take jsons from folder located in resources. For it I implemented this method:
protected def getListOfJsonFromResources(path: String): List[String] = {
val source = Source.fromInputStream(Thread.currentThread().getContextClassLoader.getResourceAsStream(path))
println(source)
val list = source.getLines().map{file =>
Source.fromInputStream(Thread.currentThread().getContextClassLoader.getResourceAsStream(path + file))
.mkString
}.toList
source.close()
list
}
It's work fine in IDE but return nothing when I run my jar.
I know that problem is in val source as in jar it return empty iterator.
I tried already use this.getClass().getResourceAsStream(), this.getClass().getClassLoader().getResourceAsStream() and rewrite this method as java method.
I generate JAR in Idea (Build>Build Artifacts>Build). This files is inside JAR with correct path.
I use Apache Maven 3.6.3
My res folder: resources/folder/json/jsonFolder path:folder/json/jsonFolder/
How should I change this method to get list of jsons from given folder?
Thank, in advance.
The proper usage is actually MyClass.class.getResourceAsStream. After all, getClass().getRAS() would fail if your code is subclassed. However, I assume it isn't - so that change will improve the style of this code and future proof it, but it probably won't directly fix the issue.
What MyClass.class.getRAS does, is look in the exact same place that the MyClass.class file is at. For example, if you have a jar with:
META-INF/MANIFEST.MF
com/foo/app/MyClass.class
app-icon.png
com/foo/app/save.png
And you run MyClass, then MyClass.class.gRAS("save.png") will work out. As weill MyClass.class.gRAS("/app-icon.png") - note the leading slash.
Thus, if gRAS isn't working for you here, the conclusion is that you're either specifying the wrong path, or the file you need to be included with your app is not being included by your build tooling.
You haven't shown anything relevant from your build scripts, so there's not much to say about how to fix this. But I can give you the tools you need to debug the problem so you can fix it yourself, with this useful trick:
MyClass.class.getResource("MyClass.class")
works for any class. Print it (System.out.println the URL that falls out of the above call), and you will see the URL, which tells you exactly which of the no doubt many variants of MyClass is actually being used (by your IDE's build-on-save, by sbt's build tooling, in the jar file produced by sbt during the dist phase, and who knows how many more exist somewhere on disk!).
Now use standard computer tools (Mac: Finder, windows: Explorer, or just use the command line) to navigate to the actual location and check for the existence of this resource file. Note that jar files are just zip files; unzip -l somejar.jar is useful here.
If you see the file, well, now you know where that file is relative to MyClass.class, and now you know what to feed to the gRAS call. Note that .. is not a good idea; if it's not in the same dir as your class and not in any subdir, then use the leading slash to go off of the 'root' of the jar file or classpath root directory.
If you don't see the file, well, now you know that your build is broken. Search the web (or ask in a separate question here on SO) on how to fix that, and now you don't need to repeatedly build and run the entire app to figure it out; you can simply keep scanning the jar file produced by the build tool until the resource file shows up in the right spot.
NB: ClassLoader.getSystemCLassLoader.getResource, getThreadContext().getResource, getClass().getResource - these are all wrong. Don't do that. It'll probably also work, but it's more code and will break in various circumstances. MyClass.class.getResource does exactly what you want, is idiomatic, and is one of the shortest forms.

Create file without listing full path - Java

At the moment I create a file like this:
new File("C:\\Users\\user\\Projects\\javaProject\\src\\com\\javaProject\\package\\file.xml");
So far listing the whole path is the only way I can get the file to be create inside 'package' otherwise if I just use:
new File("file.xml");
it just gets created in the source directory and if I use:
new File("package\\file.xml");
it just throws errors
Have you tried using a relative path?
new File("com\\javaProject\\package\\file.xml");
Your Java code should not be creating files in your package directory.
Eventually, you're going to want to deploy your code, which usually means packaging it in a Jar file. You cannot modify a Jar file from within the code running in the Jar file.
Even if that might be physically possible, don't do it. Besides, the code to modify a Jar file is way different from your current code.
Yes I did in the same way like janos but i think File.separator is better then / or \ because someday your program might run on a platform developed in a far-off land, a land of strange things and stranger people, where horses cry and cows operate all the elevators. In this land, people have traditionally used the ":" character as a file separator, and so dutifully the JVM obeys their wishes.

Libraries to create jar from a Java file

I am trying to write a program in Java, which would collect a specified set of files from the physical location and place them in a jar in a certain directory.
I know I can use java.util.jar package for this. The package is great for sure, but I was wondering if there are any third party libraries that anyone at SO has used which they could recommend.
TL;DR: pick up files, create jar by placing them in pre-defined directories, all at run time in a java file.
P.S: I did not find any similar references to this question, but if there are then please refer me. Also, the title might be misleading, but I didn't find better words to explain my problem.
EDIT 1: I am not in anyway saying java.util.jar is bad or incomplete. All I am asking is if anyone has used any alternative solutions!
EDIT 2: I am trying to create the jar from inside the java program. The jar can be pretty big (~500mb) too. Trying to jar media files as well. So simply put, I pick up various files from certain locations on my drive and try to create a jar file by placing them in standard locations.
Thanks,
Ivar
Look at the java.util.zip package. Jars are just zip files with some extra stuff in 'em

Is .jar archive not anymore useful if I need to apply a patch to a library?

I've downloaded Lucene jar file. I'm including it in my classpath to run my Lucene application.
However, I now need to apply a patch. Should I download the Lucene sources, apply the patch and compile.. right ? I cannot use anymore the jar...
thanks
ps. I also need to know how to apply patches in java actually... what's the command from terminal ?
There may be alternative approaches, but creating a completely new jar file would be your best bet, IMO. It'll be a lot harder to mess up with subtle issues than providing a second jar file to take priority for just some classes, etc.
I'm not sure if I'm right but in my opinion to apply the patch your corrected classes have to appear on the class path before the incorrect ones. So you can make a jar containing corrected classes and put it somewhere on the class path earlier than the original lucene jar.
To add a class or update an existing one, you'll use the same jar command but with that -u option. try jar -help from the terminal.
Jon Skeet is correct -- creating a new jar is the best thing to do. You can just put the directory tree containing the new .class files on your classpath before the old jar file, but that's messy and error-prone.
To apply the patch, use the command patch -p<n> <patch_file.txt in the root directory of the source.
where <n> is the number of directories to strip from the pathnames in the patch to match the pathnames in the source tree -- start with 0.

Why do Java source files go into a directory structure?

as weSuppose that I am creating a Java project with the following classes
com.bharani.ClassOne
com.bharani.ClassTwo
com.bharani.helper.HelperOne
com.bharani.helper.support.HelperTwo
with files put immediately under the folder 'src'
src/ClassOne.java
src/ClassTwo.java
src/HelperOne.java
src/HelperTwo.java
and compile them using the command
$ javac -d classes src/*.java (assuming that classes directory exists)
The compiler compiles these files and put the class files in appropriate sub-directories inside the 'classes' directory like this
classes/com/bharani/ClassOne.class
classes/com/bharani/ClassTwo.class
classes/com/bharani/helper/HelperOne.class
classes/com/bharani/helper/support/HelperTwo.class
Because the spec mandates that the classes should go inside appropriate directory structure. Fine.
My question is this: When I use an IDE such as Eclipse or NetBeans, they create the directory structure for the source code directory ('src' directory here) as well. Why is that? Is it mandatory? Or, is it just a convention?
Thanks.
Mainly convention. It makes sense for the source to mirror the binary structure.
Also, if you have two classes with the same name (but in different packages), how would you store the source if not in different directories?
Keeping the source in just one folder is fine for small projects, but once you have a larger project (hundreds of classes), grouping the source into packages makes things far more manageable.
Is it mandatory?
No
Or, is it just a convention?
Yes, to reflect your package structure in your source tree.
I always thought that Java's package is a little bit broken:
it seems to be hierachical, but it is not.
it is a simple (unique) prefix to define seperate plain namespaces.
I thought it was mandatory, but your experience suggests otherwise. Either way, it's just common sense, right? Large projects have so many source files - why make life more complicated by having different structures for your source and your class files?

Categories