Java Nio Zip file - java

It seems a really stupid thing but I can't see what I am doing wrong.
I have a folder that contains several zip files. Every zip file contains at least one file named sometingXYZsomething. I want to read every file sometingXYZsomething without unzipping every single zip, so, on the fly let's say.
My code is:
try (Stream<Path> paths = Files.walk(Paths.get(FOLDER_NAME)))
{
paths
.filter(p -> p.toString().contains("XYZ"))
.forEach(p -> readFileXYZ(Paths.get(p.getName())));
}
catch (IOException e)
{
e.printStackTrace();
}
And
private static void readFileXYZ(Path pathFile)
{
try {
Files.lines(pathFile).forEach(System.out::println);
} catch (IOException ex)
{
ex.printStackTrace();
}
}
The test folder has one zip, that contains a txt document testFileXYZ.txt and I get this exception
java.nio.file.NoSuchFileException: testFileXYZ.txt
testFileXYZ.txt
at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:79)
How can I get a stream of the txt file in the zip without extracting it?

The problem you've got is that you're not actually unzipping the content of the ZipFile. The ZipFile.stream() allows you to iterate through the Zip metadata (the list of file names in the Zip) but doesn't actually unzip the content for you to read. To do that, you need to use an InputStream acquired from the ZipFile, and then read that to get your content. I've provided an example of this below. There are other ways of doing this (e.g. using a ZipInputStream) but I wanted to base my example on the code you supplied. Hope this helps!
private static void openZip(String zipPath)
{
try (ZipFile zipFile = new ZipFile(zipPath))
{
zipFile.stream()
.filter(p -> p.toString().contains("XYZ"))
.forEach(p -> readFileXYZ(p, zipFile));
}
catch (Exception e)
{
e.printStackTrace();
}
}
private static void readFileXYZ(ZipEntry zipEntry, ZipFile zipFile)
{
try {
InputStream inputStream = zipFile.getInputStream(zipEntry);
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
bufferedReader.close();
}
catch (IOException ex)
{
ex.printStackTrace();
}
}

Related

Java print writer seems to detect file, but it does not write

I am using Netbeans on OS X and cannot seem to write text to a text file that I have in a package named "assets".
Below is the way I tried to accomplish writing to the text file and so far my method of doing this is not working.
The way I tried to approach this problem was converting a string to url, then converting the url to a uri. Then I used the uri for the new file parameter. After I tried to write a string using the class print writer.
public class Experiment {
File createFile(String path) {
java.net.URL url = getClass().getResource(path);
URI uri;
try {
uri = url.toURI();
}
catch (URISyntaxException e) {
uri = null;
}
if ((url != null) && (uri != null)) {
System.out.println("file loading sucess");
return new File(uri);
}
else {
System.out.println("Error file has not been loaded");
return null;
}
}
File file = createFile("/assets/myfile.txt");
public static void main(String[] args) {
Experiment testrun = new Experiment();
try {
PrintWriter writer = new PrintWriter(new FileWriter(testrun.file));
writer.println("it works");
writer.flush();
writer.close();
System.out.println("string was written");
}
catch (IOException e) {
System.out.println("there was an error while writing");
}
}
}
The output given from my try catch statements say that the file write code was executed.
file loading sucess
string was written
BUILD SUCCESSFUL (total time: 2 seconds)
I have also tried using absolute string paths for making a new file, but with null results. I am running out of ideas and hoping for some guidance or solution from somebody.

How to place a file for jar and read it with FileInputStream

This is the code
public static void readCharacters() {
try (FileInputStream fi = new FileInputStream("main/characters.dat"); ObjectInputStream os = new ObjectInputStream(fi)) {
characterList = (LinkedList<Character>) os.readObject();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
This is the structure:
And this is the Error
java.io.FileNotFoundException: main\characters.dat (The system cannot find the path specified)
What I want is to include the characters.dat file in my jar, and be able to read and write it while the program runs. Is there a different way to write the path? or to put the .dat file in a different position.
Also the writing method:
public static void writeCharacters() {
try (FileOutputStream fs = new FileOutputStream("main/characters.dat"); ObjectOutputStream os = new ObjectOutputStream(fs)) {
System.out.println("Writing Characters...");
os.writeObject(characterList);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
You can't. You can do one or the other. JAR files are not file systems, and their entries are not files. You can read it with an input stream:
InputStream in = this.getClass().getResourceAsStream("/main/characters.dat");
Check it for null before proceeding.
The jar is for read-only resources. You can use it for the initial file, as a kind of template.
Path path = Paths.get(System.getProperty("user.home") + "/myapp/chars.dat");
Files.mkdirs(path.getParentPath());
if (!Files.exists()) {
try (InputStream in =
Controller.class.getResourceAsStream("/main/characters.dat")) {
Files.copy(in, path);
}
}
The above copies the initial.dat resource from the jar to the user's home "myapp" directory, which is a common solution.
System.getProperty("user.dir") would the running directory. One can also take the jar's path:
URL url = Controller.class.getResource("/main/characters.dat");
String s = url.toExternalForm(); // "jar:file:/.... /xxx.jar!/main/characters.dat"
From that you can also construct the jar's directory. Mind to check Windows, Linux, spaces and such.
URL url = Controller.class.getProtectionDomain().getCodeSource().getLocation();
The solution above risks a NullPointerException, and works a bit differenly running inside the IDE or stand-alone.
Important note:
When using getResourceAsStream, you must start your path by slash /, this specifies the root of your jar, .getResourceAsStream("/file.txt");
In my case my file was a function argument, String filename, I had to do it like this:
InputStream in = this.getClass().getResourceAsStream("/" + filename);

Only meta/inf file available when exploring jar content

I am trying to read the content of a jar in a folder accessible from the root directory of my project, the jar is correctly found, however, my code only prints the name of the META-INF file, here's what i tried so far:
public static void provideClassList(String jarName) {
List<String> classNames = new ArrayList<String>();
ZipInputStream zip;
try {
zip = new ZipInputStream(new FileInputStream(StaticValues.JARS_PATH.concat(jarName)));
for (ZipEntry entry = zip.getNextEntry(); entry != null; entry = zip.getNextEntry()) {
System.out.println(entry);//PRINTS META-INF/
if (!entry.isDirectory() && entry.getName().endsWith(".class")) {
String className = entry.getName().replace('/', '.');
classNames.add(className.substring(0, className.length() - ".class".length()));
}
zip.close();
}
// explore content (THIS IS ACTUALLY EMPTY)
for (String className : classNames) {
try {
Class<?> clazz = Class.forName(className);
System.out.println(clazz.getCanonicalName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException ex) {
}
}
I cant see any permissioning issue, also, i have opened the jar file manually from console and the content that i expect to find is all there.
Those are the properties i see from eclipse:
You are calling zip.close(); inside of the for loop, that is propably the reason you only get the first entry in the jar. Move it outside of the for loop, or even better, use a try-with-resources Statement.
try (FileInputStream fis = new FileInputStream(StaticValues.JARS_PATH.concat(jarName);
ZipInputStream zip = new ZipInputStream(fis)) {
// code for iterating goes here
}

Reading a file from a Res folder

I have put a file "template.html" inside RAW folder and I want to read it into a InputStream. But it is returning me null. Can't understand what is wrong in the below code
e.g. fileName passed as parameter is "res/raw/testtemplate.html"
public String getFile(String fileName) {
InputStream input = this.getClass().getClassLoader().getResourceAsStream(fileName);
return getStringFromInputStream(input);
}
Also, there might be a better solution by putting these files in a particular subfolder and putting it inside Asset folder but then I believe I would need to pass context in AssetManager. I don't understand that solution, sorry I am new to android development. Can someone shed some light regarding how this approach can be achieved.
EDIT
I have started implementing this solution with Assets. Below method is supposed to return a string containing the entire text of the file stored as template.html.
getFile("template.html") // I am sending extension this time
Problem getting error getAssets() is undefined.
public String getFile(String fileName) {
BufferedReader reader = null;
StringBuilder sb = new StringBuilder();
String line;
try {
reader = new BufferedReader(new InputStreamReader(getAssets().open(fileName)));
while ((line = reader.readLine()) != null) {
sb.append(line);
}
}
catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
use this
new BufferedInputStream(getResources().openRawResource(filepath));
this will return a buffered input stream
The file name should be without extension :
InputStream ins = getResources().openRawResource(
getResources().getIdentifier("raw/FILENAME_WITHOUT_EXTENSION",
"raw", getPackageName()));
For this purposes uses assets folder:
assets/
This is empty. You can use it to store raw asset files. Files that you save here are compiled into an .apk file as-is, and the original filename is preserved. You can navigate this directory in the same way as a typical file system using URIs and read files as a stream of bytes using the AssetManager. For example, this is a good location for textures and game data.
So, you could easy get access at assets with context: context.getAssets()
BufferedReader reader = null;
try {
reader = new BufferedReader(
new InputStreamReader(context.getAssets().open("filename.txt")));
}
} catch (IOException e) {
//log the exception
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
//log the exception
}
}
}

Using java.io library in eclipse so FileInputStream can read a dat file

Goal: Print the data from a .dat file to the console using Eclipse.
(Long-Term Goal): Executable that I can pass a .dat file to and it creates a new txt file with the data formatted.
The .dat: I know the .dat file contains control points that I will need to create a graph with using ECMAScript.
Eclipse Setup:
Created Java Project
New > Class .. called the Class FileRead
Now I have FileRead.java which is:
1/ package frp;
2/
3/ import java.io.BufferedReader;
4/ import java.io.File;
5/ import java.io.FileReader;
6/
7/ public class FileRead {
8/
9/ public static void main(String[] args) {
10/ FileReader file = new FileReader(new File("dichromatic.dat"));
11/ BufferedReader br = new BufferedReader(file);
12/ String temp = br.readLine();
13/ while (temp != null) {
14/ temp = br.readLine();
15/ System.out.println(temp);
16/ }
17/ file.close();
18/ }
19/
20/ }
Please note this approach was borrowed from here: https://stackoverflow.com/a/18979213/3306651
1st Challenge: FileNotFoundException on LINE 10
Screenshot of Project Explorer:
QUESTION: How to correctly reference the .dat file?
2nd Challenge: Unhandled exception type IOException LINES 12, 14, 17
QUESTION: How to prevent these exceptions?
Thank you for your time and effort to help me, I am recreating Java applets using only JavaScript. So, I'm looking to create java tools that extract data I need to increase productivity. If you are interested in phone/web app projects involving JavaScript, feel free to contact me 8503962891
1. Without changing your code, you must place the file in the project's root folder.
Otherwise, reference it as src/frp/dichromatic.dat
2. Doing something like this:
public static void main(String[] args) {
FileReader file = null;
try {
file = new FileReader(new File("dichromatic.dat"));
} catch (FileNotFoundException e1) {
System.err.println("File dichromatic.dat not found!");
e1.printStackTrace();
}
BufferedReader br = new BufferedReader(file);
String line;
try {
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.err.println("Error when reading");
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
System.err.println("Unexpected error");
e.printStackTrace();
}
}
}
}
3. Creation of a new txt file "formatted". In this example, the formatting will be settings the characters to uppercase.
public static void main(String[] args) {
FileReader file = null;
BufferedWriter bw = null;
File outputFile = new File("output.formatted");
try {
file = new FileReader(new File("dichromatic.dat"));
} catch (FileNotFoundException e1) {
System.err.println("File dichromatic.dat not found!");
e1.printStackTrace();
}
try {
bw = new BufferedWriter(new FileWriter(outputFile));
} catch (IOException e1) {
System.err.println("File is not writtable or is not a file");
e1.printStackTrace();
}
BufferedReader br = new BufferedReader(file);
String line;
String lineformatted;
try {
while ((line = br.readLine()) != null) {
lineformatted = format(line);
bw.write(lineformatted);
// if you need it
bw.newLine();
}
} catch (IOException e) {
System.err.println("Error when processing the file!");
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
System.err.println("Unexpected error");
e.printStackTrace();
}
}
if (bw != null) {
try {
bw.close();
} catch (IOException e) {
System.err.println("Unexpected error");
e.printStackTrace();
}
}
}
}
public static String format(String line) {
// replace this with your needs
return line.toUpperCase();
}
I would strongly recommend spending some time reading through the Java Trails Tutorials. To answer your specific question, look at Lesson: Exceptions.
To oversimplify, just wrap the file-handling code in a try...catch block. By example:
package frp;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
public class FileRead {
public static void main(String[] args) {
try {
FileReader file = new FileReader(new File("dichromatic.dat"));
BufferedReader br = new BufferedReader(file);
String temp = br.readLine();
while (temp != null) {
temp = br.readLine();
System.out.println(temp);
}
file.close();
} catch (FileNotFoundException fnfe) {
System.err.println("File not found: " + fnfe.getMessage() );
} catch (IOException ioe) {
System.err.println("General IO Error encountered while processing file: " + ioe.getMessage() );
}
}
}
Note that ideally, your try...catch should wrap the smallest possible unit of code. So, wrap the FileReader separately, and "fail-fast" if the file isn't found, and wrap the readLine loop in its own try...catch. For more examples and a better explanation of how to deal with exceptions, please reference the link I provided at the top of this answer.
Edit: issue of file path
Not finding the file has to do with the location of the file relative to the root of the project. In your original post, you reference the file as "dichromatic.dat" but relative to the project root, it is in "src/frp/dichromatic.dat". As rpax recommends, either change the string that points to the file to properly reference the location of the file relative to the project root, or move the file to project root and leave the string as-is.

Categories