How do i modify a .yaml File in an other .jar File? - java

I am setting up a .jar file loader, and I want to modify a .yml File in the .jar File before I use it in a method like this. Bukkit().getPluginManager().loadPlugin(File file); If i understand it correctly, i have also have to save the changes.
I don't have the knowledge of how to do this, because I have never used files in a way like this before in Java 8. If there is somebody out, I would be very happy
Here the method where I load the jar Files, and then the place, where I want to modify and save it
for (final File file : folder.listFiles()) {// Get all files in the folder
if (!file.isDirectory()) {// Only use the file, if it is a regular file
try {
if (FileManager.isJarFile(file)) {
// found a jar file
System.out.println("Found jarfile with possible yml.file in it: " + file.getName());
/*
*
* Here it should modify the .jar file like above, bevore it gets loaded
*
*/
}
} catch (IOException e) {
// Didn't found that jar file, can ignore it
}
}
}
Short: So what should the method do? It should load the jar file, load a .yml file in it, modify the file, and then save the changes in the .jar file again.

Related

Jar classpath resources read failing which is triggerred from other executable jar

With reference to the link: How do I read a resource file from a Java jar file?
I am trying using your code base and trying to read content of sample.csv which is residing in my project directory src/main/resources. I am unable to read the content, it says can not read file. Output:
[Can not read file: sample.csv]
//This is added within your while loop after this check /* If it is a directory, then skip it. */
I mean when file is detected then next is my below code snippet added to read the file content
if(entry.getName().contains("sample.csv")) {
File f1 = new File("sample.csv");
if(f1.canRead()) {
List<String> lines = Files.readAllLines(f1.toPath());
System.out.println("Lines in file: "+lines.size());
} else {
System.out.println("Can not read file: "+entry.getName());
}
}
Can anyone educate me what I am doing wrong here, how can I make it working?
My requirement is this:
(My micro-service) Service.jar imports Parser.jar library in its pom.xml
(My library) - Parser.jar has FnmaUtils-3.2-fieldMapping.csv file in src/main/resources directory
There is a FnmaUtils class that loads the FnmaUtils-3.2-fieldMapping.csv within its constructor, this class is part of Parser.jar - Here I am trying to read the content FnmaUtils-3.2-fieldMapping.csv, this step is keep failing with below error, tried all possible options shown in [How do I read a resource file from a Java jar file?
public FnmaUtils() {
String mappingFileUrl = null;
try {
Resource resource = new ClassPathResource("FnmaUtils-3.2-fieldMapping.csv");
mappingFileUrl = resource.getFile().getPath();
loadFnmaTemplate(mappingFileUrl);
} catch (Exception e) {
e.printStackTrace();
LOGGER.error("Error loading fnma template file ", e);
}
}
Getting error:
java.io.FileNotFoundException: class path resource [`FnmaUtils-3.2-fieldMapping.csv`] cannot be resolved to absolute file path because it does not reside in the file system: `jar:file:/home/ravibeli/.m2/repository/com/xxx/mismo/util/fnma-parser32/2018.1.0.0-SNAPSHOT/fnma-parser32-2018.1.0.0-SNAPSHOT.jar!/FnmaUtils-3.2-fieldMapping.csv`
at org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:218)
at org.springframework.core.io.AbstractFileResolvingResource.getFile(AbstractFileResolvingResource.java:52)
at com.xxx.fnma.util.FannieMaeUtils.<init>(FannieMaeUtils.java:41)
at com.xxx.fnma.processor.FNMA32Processor.<init>(FNMA32Processor.java:54)
at com.xxx.fnma.processor.FNMA32Processor.<clinit>(FNMA32Processor.java:43)
What is going wrong here?
Try
InputStream in = this.getClass().getClassLoader()
.getResourceAsStream("SomeTextFile.txt");
Be sure the resource is in your classpath.

Proper packaging of runnable Jar project in netbeans

So my task is to create a small program that displays a list of media files and run these media files with default OS media player separately.
My current solution was to create a package that holds all media files, something like:
-com.media
|_a.mp4
|_b.mp4
The following code copies to a temp dir the selected mp4, then runs the default os media player:
public File copyTempMedia(File tempAppFolder, String videoName) {
URL f = getClass().getResource(String.format("%s/%s", Constants.MEDIA_LOCATION, videoName));
File from = new File(f.getPath());
File to = new File(tempAppFolder.getAbsolutePath());
try {
FileUtils.copyFileToDirectory(from, to);
} catch (IOException ex) {
Logger.getLogger(MediGUIModel.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Temp video copied: " + to.getAbsolutePath() + "/" + to.getName());
return to;
}
public void triggerMediaPlayer(String fileLocation) {
System.out.println("Triggering media player: " + fileLocation);
try {
if (OPERATIN_SYSTEM.contains("Linux")) {
Runtime.getRuntime().exec("sh -c " + fileLocation);
} else if (OPERATIN_SYSTEM.contains("Windows")) {
Runtime.getRuntime().exec("cmd /c " + fileLocation);
}
} catch (IOException ex) {
Logger.getLogger(MediGUIModel.class.getName()).log(Level.SEVERE, null, ex);
ex.printStackTrace();
}
}
When I run the program through Netbeans it works as espected, but when I do a clean/build the run the .jar created from the build, the media file doesn't seem to be read, so my questions are:
Why does it work through Netbeans and not through build .jar ?
Is this the best solution to this problem ?
Should I package the media differently ?
Thanks in advance.
Edit
So after running through console instead of double clicking jar, is get a null pointer exception in the line where I read the file:
URL f = getClass().getResource(String.format("%s/%s", Constants.MEDIA_LOCATION, videoName));
Why does it work in Netebeans but not on build/jar ?
Is there another place in the jar I could place the media files, so that they are read with no problem through getResource or getResourceAsStream ?
When you run the project in NetBeans, it isn't running the executable jar like java -jar yourproject.jar. Instead it sets the classpath to build/classes sort of like java -cp build/classes com.media.YourMainClass. This means your video files are actual files located in yourproject/build/classes/com/media, and they can be accessed as normal files in the filesystem and copied like a normal file. When you run from the jar, the files are packed in the jar file and can't be copied using simple file copy commands.
Instead of getting the URL by calling getClass().getResource(), try getting an InputStream by calling getClass().getResourceAsStream(). You can then write a simple loop to copy the bytes from the input stream to your temporary file.
This snippet may be helpful:
BufferedInputStream result = (BufferedInputStream) getClass().getResourceAsStream("/com/media/a.mp4");
byte[] bytes = new byte[4098];
try {
result.read(bytes);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(new String(bytes));
You'll need to read the bytes in a loop or something but that should work without needing a separate jar.
I think it's not a good idea to put your media files in the jar because you need to rebuild the project if you want to change one and the jar size will grow.
Use:
File from = new File(String.format("%s/%s", Constants.MEDIA_LOCATION,videoName));
To load your files from the same folder as the jar.
If you want to keep the medias in the jar, create a Maven project and put the mp4 in src/main/resources.
Use maven to create a fat jar and the src/main/resources will be included in the jar.
See 'maven-shade-plugin' to configure the pom.xml and https://www.mkyong.com/maven/create-a-fat-jar-file-maven-shade-plugin/
Then you can use the others maven's great properties!
See Reading a resource file from within jar
Edit
After some tries, i can't get it right with 'getResource' from the jar.
The path you get from within the jar is like:file:/C:/.../JavaApplication4/dist/JavaApplication4.jar!/test.txt
and not recognized as a valid filesystem path.
You can use 'getResourceAsStream' and copy the file from the jar to the local folder.
InputStream in;
OutputStream out;
IOUtils.copy(in,out);
in.close();
out.close();
Ok so I found a solution:
Create a separate project with media.*.mp4.
Export as Jar library.
Import library to desktop app.
Make sure library is in classpath.
This solution works for me...
If anyone has a better solution, happy to hear, hopefully before bounty is up :)

Java - Create a file in the same directory as the .jar if it doesn't already exist

I am stuck at two parts really.
A) I need the program to find the directory of the RUNNING JAR FILE and check if there is a file called "credits.txt" in the same directory.
B) If not, it would create the file in the SAME DIRECTORY.
The main issue is not being able to get the path of my file.
Say the running jar file was in a folder called "Server", the program would save the name "Server" in a string and then check if a file exists in that string. If so, do nothing, otherwise create the file.
#Override
public void onEnable(){
getLogger().info(ChatColor.GREEN + "Credits has been enabled!");
File file = new File("Credits.txt");
//HERE I NEED THE PROGRAM TO CHECK WHAT DIRECTORY THE RUNNING JAR FILE IS FROM
if (file.exists(//IN THE SAME DIRECTORY AS THE RUNNING JAR FILE)){
getLogger().info(ChatColor.DARK_GREEN + "Credits File Exists");
}else{
getLogger().info(ChatColor.DARK_RED + "Credits File Doesn't Exist!");
//HERE IT NEEDS TO CREATE THE FILE IN THE SAME DIRECTORY OF THE JAR FILE "credits.txt"
}
If you're making a Bukkit plugin, you can use getDataFolder() in your main class. Then you can check if it exists and then create it if it doesn't.
public void onEnable(){
getLogger().info(ChatColor.GREEN + "Credits has been enabled!");
File pluginDirectory = getDataFolder(); //getting the data folder
if(!pluginDirectory.exists()){
pluginDirectory.mkdir(); //Creating the plugin data folder if it doesn't exist.
}
File file = new File(pluginDirectory+File.seperator+"Credits.txt"); //Credits.txt inside the plugin directory
if (file.exists()){ //Checking if Credits.txt exists
getLogger().info(ChatColor.DARK_GREEN + "Credits File Exists");
}else{
getLogger().info(ChatColor.DARK_RED + "Credits File Doesn't Exist!");
file.createNewFile(); //You probably need to create it too
}
}
If you want to create it for storing settings, consider using getConfig() instead of creating a file yourself. It's much easier.

Write to a .txt file in a package

I would like to write to a .txt file that is inside a package. I can get it to read from the exact location the .txt file is stored but not from inside the package. I'm assuming it is using class loaders but I cannot seem to get it to work.
Here is what I have so far.
public void writeFile(String fileLocation) {
Writer output = null;
File file = new File(fileLocation);
try {
output = new BufferedWriter(new FileWriter(file));
output.append("WRITING TEST");
output.close();
} catch (IOException ex) {
System.out.println("Couldn't write to file.");
}
}
Then I use this in another class to write.
WriteFile writeFile = new WriteFile();
writeFile.writeFile("src/com/game/scores.txt");
I understand that if using class loaders you remove "src/" because that will no longer exist when the program is compiled in a .jar.
It is not possible to write or update a file inside jar. Since jar itself is a file.
Please refer this link.
Write To File Method In JAR
You could use a class in that package to give you the location of the folder.
Try something like
public URL getPackageLocation() {
return getClass().getResource(".");
}
This should give you the location of the folder from which this method is being called from.
From the comments you already know that you cann't write to a file, which resides in a JAR file. At best what you can do, is creating your file, relative to the path where the JAR is located like bellow:
mylocation
|-- my-jar.jar
|-- com
|--game
|--myfile.txt
I would like to write to it to update the scores in my game as the
user goes through the levels.
While it might be possible to write to the JAR file, I don't recommend it for this use case. Just write it somewhere at:
Path userdir = Paths.get(System.getProperty("user.home"), ".myApp", "<my app version>");
You can't write into Jar file. Writing into Jar file is not recommendable. You can write outside the jar file.
Please refer this and this stack overflow question for more details.

writing (modifying or adding) a file inside a zip

I've followed the instructions in
this thread, using the code in there I've been able to add a file to a zip file without uncompressing and recompresing it, but i have a problem, let me show you my code:
private void saveFileIntoProjectArchive(Path pathOfFile) {
this.projectArchiveFile.setWritable(true, false);
Path zipFilePath = Paths.get(this.projectArchiveFile.getAbsolutePath()),
pathToSaveInsideZIP = null;
FileSystem fs;
try {
fs = FileSystems.newFileSystem(zipFilePath, null);
pathToSaveInsideZIP = fs.getPath(pathOfFile.toString().substring((int) this.transactionalProjectFolder.getAbsolutePath().length()));
System.out.println("Coping from:\n\t"+pathOfFile+"\nto\n\t"+pathToSaveInsideZIP);
Files.copy(pathOfFile, pathToSaveInsideZIP, REPLACE_EXISTING);
System.out.println("Done!!!");
fs.close();
} catch (java.nio.file.NoSuchFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
projectArchiveFile.setWritable(false, false);
}
what I'm trying to do is, i have many files for a same project, that project is an archive (ZIP, which in the code is referenced by a java.io.File called projectArchiveFile, an instance variable of my class) containing all of those files, when I want to work with certain file inside my archive, i uncompress only that file into a folder which has an structure identical to the one inside my archive (ZIP, projectArchiveFile), the reference to that folder is a java.io.File called transactionalProjectFolder, also an instance variable of my class. But is giving me this error:
coping from:
C:\Dir1\Dir2\Dir3\Begin of Archive stucure\Another folder replica of the archive structure\An Excel File.xlsm
to
\Begin of Archive stucure\Another folder replica of the archive structure\An Excel File.xlsm
java.nio.file.NoSuchFileException: Begin of Archive stucure\Another folder replica of the archive structure\ at com.sun.nio.zipfs.ZipFileSystem.checkParents(ZipFileSystem.java:846)
at com.sun.nio.zipfs.ZipFileSystem.newOutputStream(ZipFileSystem.java:515)
at com.sun.nio.zipfs.ZipPath.newOutputStream(ZipPath.java:783)
at com.sun.nio.zipfs.ZipFileSystemProvider.newOutputStream(ZipFileSystemProvider.java:276)
at java.nio.file.Files.newOutputStream(Files.java:170)
at java.nio.file.Files.copy(Files.java:2826)
at java.nio.file.CopyMoveHelper.copyToForeignTarget(CopyMoveHelper.java:126)
at java.nio.file.Files.copy(Files.java:1222)
the rest of the stack trace are my classes.
I've been able to write in the root of the archive(zip), but whenever i try to write inside of a folder which is inside of the archive (zip) it fails, as you can notice in the stack trace, it says that java.nio.file.NoSuchFileException: Begin of Archive stucure\Another folder replica of the archive structure\ and it stops right before the name if the file which I'm trying to copy, I'M ENTIRELY SURE that the path inside the zip exist and it is appropriately spelled it just do not want to write (I've trying with Files.copy and Files.move) the file inside the archive, I've been stuck in this for a month, I don't know what else to do, any suggestion will be appreciated!!!
thanks in advance! :)...
Even tho you are sure the path exists, I would for troubleshooting add below row and see what directory structure it creates.
The error indicate the directories are missing inside the zip. Could be you are using some weird folder names not supported by zip etc..
System.out.println("Coping from:\n\t"+pathOfFile+"\nto\n\t"+pathToSaveInsideZIP);
Files.createDirectories(pathToSaveInsideZIP); // add this row
Files.copy(pathOfFile, pathToSaveInsideZIP, StandardCopyOption.REPLACE_EXISTING);
System.out.println("Done!!!");
I'll recommend you to try out the TrueZip it's easy to use, it exposes any archive into a virtual file system, then you can append, delete or edit any file inside the archive easily.

Categories

Resources