How to delete a file inside zip file in android - java

I want to delete a file from a zip file without extracting it in android. I first did it with java using the following code
Path zipFilePath = Paths.get(filePaths); //gave the path of the zip with zip file name
try( FileSystem fs = FileSystems.newFileSystem(zipFilePath, null) ){
Path pathInZipfile = fs.getPath(reVsl3); //reVsl3 String which holds the name of the file to be deleted in the zip file
zipDelLoc=reVsl3; //just assigning it for future use
System.out.println("About to delete an entry from ZIP File" + pathInZipfile.toUri() );
// Execute Delete
Files.delete(pathInZipfile);
System.out.println("File successfully deleted");
}
catch (IOException e) {
System.out.println(e+"Error here?");
}
This is working perfectly in netbeans, but its not working in ADT, the error occured in logcat
java.lang.NoClassDefFoundError: java.nio.file.Paths
Isearched for a resolution in and got a hint that android does not have ' java.nio.file.Paths' this thing,
I am looking for an alternate solution can zip4j or TrueZip will do the trick here,
i tried with truezip, but with this code
TFile archive = new TFile("archive.zip");
for (String member : archive.list())
System.out.println(member);
but archive.list() is returning null, but archive.length is returning its correct file size.
I dont know what i am doing wrong in here, i downloaded truezip 7.7 all in one jar. but i am getting an error when i give this import de.schlichtherle.io.File
please help

What version of Java are you using?
Double-check your import. It should be something something like de.schlichtherle.truezip.nio.file.TPath; When working with TrueZip, you need to import java.nio.paths even if you aren't using it and instead using truezip's flavor of paths.
Make sure you're including all the proper dependencies. I'm assuming you're using Gradle, so the dependency would look something like this:
'de.schlichtherle.truezip:truezip-file:7.7.9'
I handled a similar error with importing dependencies in a Java project using Maven. Try these things and provide your Java version.

Related

Java read and write to the resource folder

When someone opens my jar up I am opening a file selector gui so they can choose where they want to store their jar's files like config files and such. This should only take place the first time they open the jar. However, one issue with this approach is that I would have no way to know if it's their first time opening the jar since I will need to save the selected path somewhere. The best solution to this sounds like saving the selected path inside a file in the resource folder which is what I am having issues with. Reading and writing to this resource file will only need to be done when the program is actually running. These read and write operations need to work for packaged jar files (I use maven) and in the IDE.
I am able to read a resources file inside of the IDE and then save that file to the designated location specified in the file selector by doing this. However, I have not been able to do the same from a jar despite trying multiple other approaches from other threads.
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream is = classloader.getResourceAsStream("config.yml");
try {
if(is != null) {
Files.copy(is, testFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
So just to clarify when my project is loaded I need to listen for the user to select a valid path for files like my config. Then I want to write my config to that path which I can do from my IDE and is shown above but I cant figure this out when I compile my project into a jar file since I always receive a file not found error in my cmd. However, the main point of this post is so that I can figure out how to save that selected path to my resource folder to a file (it can be json, yml or whatever u like). In the code above I was able to read a file but I have no idea how to go from that to get the files path since then reading and writing to it would be trivial. Also keep in mind I need to be able to read and write to a resource folder from both my IDE and from a compiled jar.
The following code shows my attempt at reading a resource from a compiled jar. When I added a print statement above name.startWith(path) I generated a massive list of classes that reference config.yml but I am not sure which one I need. I assume it has to be one of the paths relating to my project or possible the META-INF or META-INF/MANIFEST.MF path. Either way how am I able to copy the file or copy the contents of the file?
final String path = "resources/config.yml";
final File jarFile = new File(getClass().getProtectionDomain().getCodeSource().getLocation().getPath());
if(jarFile.isFile()) { // Run with JAR file
try {
final JarFile jar = new JarFile(jarFile);
final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
while(entries.hasMoreElements()) {
final String name = entries.nextElement().getName();
if (name.startsWith(path)) { //filter according to the path
System.out.println(name);
}
}
jar.close();
} catch (IOException exception) {
exception.printStackTrace();
}
}
Also if you were wondering I got the above code from the following post and my first block of code I pasted above is actually in the else statement since the IDE code from that post also did not work.
How can I access a folder inside of a resource folder from inside my jar File?
You can't write to files inside your JAR file, because they aren't actually files, they are ZIP entries.
The easiest way to store configuration for a Java application is to use Preferences:
Preferences prefs = Preferences.userNodeForPackage(MyApp.class);
Now all you have to do is use any of the get methods to read, and put methods to write.
There is absolutely no need to write files into your resource folder inside a jar. All you need to have is a smart classloader structure. Either there is a classloader that allows changing jars (how difficult is that to implement?), or you just setup a classpath that contains an empty directory before listing all the involved jars.
As soon as you want to change a resource, just store a file in that directory. When loading the resource next time, it will be searched on the classpath and the first match is returned - in that case your changed file.
Now it could be that your application needs to be started with that modified classpath, and on top of that it needs to be aware which directory was placed first. You could still setup that classloader structure within a launcher application, which then transfers control to the real application loaded via the newly defined classloader.
You could also check on application startup whether a directory such as ${user.home}/${application_name}/data exists.
If not, create it by extracting a predefined zip into this location.
Then just run your application which would load/write all the data in this directory.
No need to read/write to the classpath. No need to include 3rd party APIs. And modifying this initial data set would just mean to distribute a new zip to be extracted from.

Cannot find and read file in Java

I am completely new to Java and I am
using somebody elses code to read a binary file
but the file will not open. I am running the code in Eclipse under Windows 10
the file is called
bookDeepDist.dat
I have put it in the project folder. The full path name which I have also tried (without success ) is
C:\Users\Alan\eclipse-workspace\readDatabase\bookDeepDist.dat
The code that fails is:
public void openBook() throws IOException {
file = getClass().getResourceAsStream(BOOKPATH[bookNr]);
if (file == null)
throw (new IOException("Could not open File "+BOOKPATH[bookNr]));
}
The error message is:
Could not open File bookDeepDist.dat
so it seems to be trying to open the correct file.
Can anybody give me any idea what could be going wrong?
The problem is, that getResourceAsStream() looks in the classpath of the running Java program. That's why it is working, when you put the file in the project folder. What you want, is a stream of the file outside of the program's classpath.
Instead of
file = getClass().getResourceAsStream(BOOKPATH[bookNr]);
try using
file = new FileInputStream(BOOKPATH[bookNr]);

getClassLoader().getResource("Configuration.xml").getPath() does not work inside a jar

I've created a maven based java project which has resources directory (src/java/resources) and in it some xml files and maven copies them into target/classes/resources (target/classes is my classpath).
To know the content of an xml file, I use:
new FileInputStream(Main.class.getClassLoader().getResource("Configuration.xml").getPath());
Main.class.getClassLoader().getResource("Configuration.xml").getPath() gives me the full path of the xml: "c:\project...\Configuration.xml".
This works well on intellij.
but when I compile and package the project into a jar file I get:
Exception in thread "main" java.io.FileNotFoundException:
file:\C:\project\target\project-12.50.14-SNAPSHOT-jar-with-dependencies
.jar!\Configuration.xml
(The filename, directory name, or volume label syntax is incorrect)
That because the path: \C:\project\target\project-12.50.14-SNAPSHOT-jar-with-dependencies
.jar!\Configuration.xml cannot be a parameter into FileInputStream().
I cannot replace the getResource() to getResourceAsStream().
I need a way to adjust my jar and resources to work like it work on intellij.
I also change the xml resources files content during run-time so that is another problem with keeping them inside a jar.
Can anyone offer me a solution in which I don't have to change me code, and instead change my resources directory structure, or change the classpath, or something else that will keep my code working?
Thanks.
Update: Changed to use File, not Path.
That is because getResource returns a URL, and not all urls are files on disk, i.e. can be converted to a Path. As javadoc says "Returns [...] an empty string if [path part] does not exist".
If it absolutely must be a File or FileInputStream, because some other code you cannot change requires it, then copy the content to a temporary file:
File file = File.createTempFile("Configuration", ".xml");
try {
try {InputStream in = Main.class.getClassLoader().getResourceAsStream("Configuration.xml")) {
Files.copy(in, file.toPath()); // requires Java 7
}
// use file here, or:
try {FileInputStream in = new FileInputStream(file)) {
// use file stream here
}
} finally {
file.delete();
}
The above code could be optimized to not copy if resource is a file, but since that's only for development mode, and production mode is always a Jar and will always need the copy, using copy in development mode helps test the code.

Open resource within a jar: URI is not hierarchical

I'm trying to write a converter for specific file formats. The converted files should be filtered using a configuration file. Everything works great so far, but I have a problem concerning the reading of a file in a packaged jar.
I have the following structure for my files (Windows):
converter/src/main/resources/files/AStoXES.properties (there are 3 more property files)
If I'm executing this code in Netbeans everything works fine and the file will be read:
this.fileConfig = new PropertiesConfiguration(new File(testing.class.getClassLoader().getResource("files/AStoXES.properties").toURI()));
But if I'm packaging the jar with Apache Maven doing a clean install and run the whole program I'll get a java.lang.IllegalArgumentException: URI is not hierarchical.
After hours of spending time with Google I have found many threads with the same problem and tested lots of things but none of those proposals helped me out of this problem.
I NEED the contents of the file as a java.io.File, so using Inputstream with getResourceAsStream(argument) won't help me out, because I need to work with the properties in there.
Someone knows how to figure this one out?
Solved it by following the link (Loading a properties file from Java package) AndréStannek provided.
This way it could be read. Didn't know that PropertiesConfiguration accepts InputStreams as well.
InputStream in = testing.class.getClassLoader().getResourceAsStream("files/AStoCSV.properties");
this.fileConfig = new PropertiesConfiguration();
this.fileConfig.load(in);
try {
in.close();
} catch (IOException ex) {
Logger.getLogger(ConverterControl.class.getName()).log(Level.SEVERE, null, ex);
}
Thanks to all.
Try to get the runnig jar file, and access it as a zip file.
This may help:
How to get the path of a running JAR file?
As a solution/hack, you may create a temporary File (and an OutputStream corresponding to this File) then "write" your input stream into your output stream. You'll end up with a copy of your original File.

Android - reading txt files from external jar

I have a jar compiled with core jdk.
It contains a java class which reads a txt file.
It has a test which proves that this class works correctly.
If I include this jar in my android project and then call the java class that reads the txt file. It fails reporting: java.io.FileNotFoundException and adding a '/' to the path of the txt file which I wanted to load.
Is Android's security model stopping the txt file from being read?
My Project structure:
Android Module:
src/Loader.java [calls GetName.java]
Java Module:
test/TestGetName.java [calls GetName.java]
src/GetName.java
resources/names.txt
Summary:
TestGetName.java works
Loader.java fails. A FileNotFoundException is thrown inside GetName
Figured it out in the end. I need a condition to see if I am loading the file locally or as a resource. There is probably a neater way to do this without using a conditional.
String source = "resources/inputfile.txt";
BufferedReader fin;
InputStream inputStream = getClass().getResourceAsStream(source.substring(source.lastIndexOf("/")));
if (inputStream != null) {
fin = new BufferedReader(new InputStreamReader(inputStream));
} else {
fin = new BufferedReader(new FileReader(new File(source)));
}
Thanks for the hints about reading as a resource user77777777
It doesnt seem like the Android stopping it from accessing the file because the exception is FileNotFoundException. You should check the detailed message to confirm that. Catch the Exception and print the detailed message. That will give you a better idea. Also recheck the file path.
EDIT:
Try passing the resource name only.
getClassLoader().getResource("names.txt");
I don't know why but accepted answer didn't work for me.
Build System : Gradle
Working environment : Android Studio
I also included resources from external jar. But in order to use them I had to include full path also.
this.getClass().getResourceAsStream("/template/login.xml")
Hope this helps someone and prevents him from spending 3 hours banging his head against the wall to find an answer.

Categories

Resources