Java: Rename a file inside a .jar - java

Usually to rename a file I use:
File oldFile = new File("file path");
oldFile.renameTo(new File("file path with new name"));
But what if the file I want to rename is inside a .jar executable is there a way to rename it from there?

No, you can't do that unless you extract the JAR file, rename the file and repackage it.

You can copy a jar, one entry at a time, renaming the entry you want to change. This might be more efficient than unpacking, renaming and repacking.
You cannot rename a class file without changing all the references to that name. Without recompiling all the code, you can use a library like ObjectWebs ASM to inspect the byte code and change references to that class. If the class is referenced in a String, you may want to change the string as well.

Yes, you may rename a file within a jar. For example you may use JarEntryFilter
like this:
...
import org.springframework.boot.loader.jar.JarEntryData;
import org.springframework.boot.loader.jar.JarEntryFilter;
import org.springframework.boot.loader.jar.JarFile;
import org.springframework.boot.loader.tools.JarWriter;
import org.springframework.boot.loader.util.AsciiBytes;
...
JarWriter writer = new JarWriter(destination);
try {
JarFile filteredJarFile = sourceJar.getFilteredJarFile(new JarEntryFilter() {
#Override
public AsciiBytes apply(AsciiBytes name, JarEntryData entryData) {
String string = name.toString();
String exp = "^a.*";
if (string.matches(exp)) {
string = string.replaceFirst(exp, "replaced");
return new AsciiBytes(string);
}
return name;
}
});
writer.writeEntries(filteredJarFile);
} finally {
try {
writer.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}

Related

how to check if output folder is created in java?

I am coming to an issue where I am trying to check if output folder is there and if not create one in my code below. So, I tried doing that way as shown in my code but I dont know if its the proper a way of doing it? can you please advise. thanks for the help.
here is my code:
String outputFolder2 = Printer.getOutputFolder();
File outFileTwo = new File(outputFolder2);
if (!outFileTwo.exists()) {
if (!outFileTwo.mkdir()) {
System.out.println("Failed to make directory for: " + outputFolder2);
}
}
To check if the directory exists:
Files.isDirectory(Paths.get("/the/path"))
To create dir if not exists:
Files.createDirectories(Paths.get("/the/path"))
Simply use
dirPathFileObj.mkdir();
From java.io.File;
If the method detects that no such directory exists, it will automatically create one. Otherwise, it will simply do nothing in terms of File creation.
It's recommended to use the nio package for new code that interacts with files -- it's faster, and easier to code for. Here's how I would write that code, in the form of a junit test that I ran to verify it:
#Test
public void testSomething() {
Path dirPath = Paths.get("C:/I/do/not/exist");
Path filePath = dirPath.resolve("newFile.txt");
try {
assertFalse(Files.exists(dirPath));
dirPath = createDirectories(dirPath);
filePath = Files.createFile(filePath);
assertTrue(Files.exists(filePath));
} catch (IOException iox) {
iox.printStackTrace();
} finally {
try {
Files.deleteIfExists(filePath);
Files.deleteIfExists(dirPath);
} catch (Exception e) {
e.printStackTrace();
}
}
}
This will create C:\I\do\not\exist\newFile.txt, then delete C:\I\do\not\exist, (leaving C:\I\do\not\). For production code, you'd want to remove the asserts and fill in those catch clauses

Text and image files not included when exporting jar

I've created a project which utilizes image files as well as a text file when executed. Both the text and image files are in my project folder before I exported the project into a runnable jar, but when I ran the jar from the command line, I got a filenotfound exception caused by the program typing to read from the text file. I unzipped the jar to double check and the image and text files weren't there.
package application;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import javafx.collections.FXCollections;
public class Data {
private static Data instance=new Data();
private Map<String,String> saveEntries = new HashMap<>();
private static String fileName = "ResponseData";
public static Data getInstance() {
return instance;
}
public void exitSave() throws IOException {
Path path = Paths.get("ResponseData");
Iterator<Map.Entry<String, String>> iter = saveEntries.entrySet().iterator();
BufferedWriter bw = Files.newBufferedWriter(path);
try {
while(iter.hasNext()) {
Map.Entry<String, String> entry = iter.next();
bw.write(String.format("%s\t%s", entry.getKey(),entry.getValue()));
bw.newLine();
}
} catch (IOException e) {
new FileNotFoundException("Error when saving data");
}finally {
if(bw!=null)
bw.close();
}
}
public void updatedSaveEntry(String input, String response) {
saveEntries.put(input, response);
}
public Map<String,String> getSaveEntries(){
return this.saveEntries;
}
public void setEntry(Map<String,String> map) {
Iterator<Map.Entry<String, String>> iter = map.entrySet().iterator();
while(iter.hasNext()) {
Map.Entry<String, String> entry = iter.next();
saveEntries.put(entry.getKey(), entry.getValue());
}
}
public void loadEntries() throws IOException{
saveEntries = FXCollections.observableHashMap();
Path path = Paths.get(fileName);
BufferedReader br = Files.newBufferedReader(path);
String line;
try {
while((line=br.readLine())!=null&&!line.trim().isEmpty()) {
String[] parts = line.split("\t");
saveEntries.put(parts[0], parts[1]);
}
}finally {
if(br!=null) {
br.close();
}
}
}
}
Eclipse Runnable Jar Export
Project Folder
If you are both reading and writing to a file, then locating this file in the application jar is not appropriate as mentioned in the other answer: you should persist your data at an external location.
However, it is usual to keep the read-only resources files (such as images) in the jar. If you want to keep this approach for the images and possibly other resources, you are facing two problems:
Getting Eclipse to include the file in the jar using the Export Runnable Jar feature.
Finding the file in the jar
Including the file
The simplest is probably just to place the file in a source folder. In your project, do New -> Source Folder, give it a name (e.g., "resources"), and move your file there. Normally, if you re-run the export, the file should be in the jar.
Finding the file
Files in jar are accessed differently. See the accepted answer to Reading a resource file from within jar. Note that you don't need to include the name of your resource folder in the path, as this file will be placed at the root of your jar (you can verify this by unpacking it).
Your program is trying to read the file from your local file system and not from the jar file. So it should indeed not be included in the jar file. The program is expecting the file in the current working directory where you execute your program and that can be different if you run your project within Eclipse or if you execute the exported jar file.

Access public assets with Java in Play Framework

Is it possible to access Assets inside the Java code in Play Framework? How?
We access assets from the scala HTML templates this way:
<img src="#routes.Assets.versioned("images/myimage.png")" width="800" />
But I could not find any documentation nor code example to do it from inside the Java code. I just found a controllers.Assets class but it is unclear how to use it. If this is the class that has to be used, should it maybe be injected?
I finally found a way to access the public folder even from a production mode application.
In order to be accessible/copied in the distributed version, public folder need to be mapped that way in build.sbt:
import NativePackagerHelper._
mappings in Universal ++= directory("public")
The files are then accessible in the public folder in the distributed app in production form the Java code:
private static final String PUBLIC_IMAGE_DIRECTORY_RELATIVE_PATH = "public/images/";
static File getImageAsset(String relativePath) throws ResourceNotFoundException {
final String path = PUBLIC_IMAGE_DIRECTORY_RELATIVE_PATH + relativePath;
final File file = new File(path);
if (!file.exists()) {
throw new ResourceNotFoundException(String.format("Asset %s not found", path));
}
return file;
}
This post put me on the right way to find the solution: https://groups.google.com/forum/#!topic/play-framework/sVDoEtAzP-U
The assets normally are in the "public" folder, and I don't know how you want to use your image so I have used ImageIO .
File file = new File("./public/images/nice.png");
boolean exists = file.exists();
String absolutePath = file.getAbsolutePath();
try {
ImageInputStream input = ImageIO.read(file); //Use it
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("EX = "+exists+" - "+absolutePath);

Reading a Txt-File in a jar-File in Java

I've write a Java programm and packaged it the usual way in a jar-File - unfortunately is needs to read in a txt-File. Thats way the programm failed to start on other computer machines because it could not find the txt-file.
At the same time Im using many images in my programm but here there is no such problem: I "copy" the images to the eclipse home directory, so that they are packaged in the jar-File and usable through following command:
BufferedImage buffImage=ImageIO.read(ClassName.class.getClassLoader()
.getResourceAsStream("your/class/pathName/));
There is something similar for simple textfiles which then can be use as a normal new File()?
Edit
Ive try to solve my problem with this solution:
package footballQuestioner;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.security.auth.login.Configuration;
public class attempter {
public static void main(String[] args) {
example ex = new example();
}
}
class example {
public example() {
String line = null;
BufferedReader buff = new BufferedReader(new InputStreamReader(
Configuration.class
.getResourceAsStream("footballQuestioner/BackUpFile")));
do {
try {
line = buff.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} while (line != null);
}
}
But it gives always an NullPointerException...do I have forgotten something?
Here is as required my file structure of my jar-File:
You can load the file from the ClassPath by doing something like this:
ClassLoader cl = getClass().getClassLoader()
cl.getResourceAsStream("TextFile.txt");
this should also work:
getClass().getResourceAsStream(fileName);
File always points to a file in the filesystem, so I think you will have to deal with a stream.
There are no "files" in a jar but you can get your text file as a resource (URL) or as an InputStream. An InputStream can be passed into a Scanner which can help you read your file.
You state:
But it gives always an NullPointerException...do I have forgotten something?
It means that likely your resource path, "footballQuestioner/BackUpFile" is wrong. You need to start looking for the resource relative to your class files. You need to make sure to spell your file name and its extension correctly. Are you missing a .txt extension here?
Edit
What if you try simply:
BufferedReader buff = new BufferedReader(new InputStreamReader(
Configuration.class.getResourceAsStream("BackUpFile")));

Accessing file from package

suppose I put a file a.txt in package com.xyz and the try access it like following. Will it work?
Hi All,
import com.xyz.*;
public class Hello
{
File f = new File("a.txt");
...
}
It is not working for me. Is there any workaround?
Use Class.getResource() or Class.getResourceAsStream(). see for example the Sun demo source at http://jc.unternet.net/src/java/com/sun/WatermarkDemo/WatermarkDemo.java
I will offer the same answer as jcomeau_ictx, but a lot shorter (around 30 lines in one file as opposed to >380 in 1 source file of 5), ..and with a screenshot. ;)
import javax.swing.*;
import java.net.URL;
class GetResource {
GetResource() {
Class cl = this.getClass();
final URL url = cl.getResource( cl.getName() + ".java" );
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JEditorPane ep = new JEditorPane();
try {
ep.setPage(url);
JScrollPane sp = new JScrollPane(ep);
sp.setPreferredSize(new java.awt.Dimension(400,196));
JOptionPane.showMessageDialog(null, sp);
} catch(Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(
null,
e.getMessage() + " See trace for details.");
}
}
});
}
public static void main(String[] args) {
new GetResource();
}
}
Based on your responses to the comments above. If you are looking for a work around, just specify the path to the .txt file on the file system. Putting it in a package does not help.
new File ("a.txt")
looks for a file on the the file system and not within a package.
Please also read the javadocs on File:
http://download.oracle.com/javase/6/docs/api/java/io/File.html
However I do not see the rationale in putting the file inside a package unless you would want to use it as a resource. In which case #jcomeau_ictx has the right solution
It's depend on your class path of java from where you can run this class. If both are in same place then it will work. Then no need to define path in file. But the file was not in the classpath dir then must be define path of that file otherwise file not found.

Categories