reading files with special characters from a zipfile - java

My code reads files from a zipfile , which works fine except for files with special characters. Problematic character is 'è' ( See my code fère_champenoise )
String works="(3/(3)_juno.jpa";
String sdoesntwork="ba/battle of fère_champenoise.jpa";
ZipFile file1 = null;
try {
file1 = new ZipFile(sZipFileOld);
} catch (IOException e) {
System.out.println("Could not open zip file " + sZipFileOld + ": " + e);
}
try {
file1.getInputStream(file1.getEntry(sdoesntwork));
} catch (IOException e) {
System.out.println(sdoesntwork + ": IO Error " + e);
e.printStackTrace();
}
it throws an error but doesn't go throught the exception handler:
Exception in thread "main" java.lang.NullPointerException
at java.util.zip.ZipFile.getInputStream(Unknown Source)
at ZipCompare.main(ZipCompare.java:56)
Any Solutions ?

When constructing the zipfile, explicitly specifying the encoding: file1 = new ZipFile(sZipFileOld, Charset.forName("IBM437"));
Zip files doesn't use the default UTF-8 encoding for special characters

I believe you need to specify an encoding, UTF-8 probably. Something like this:
final InputStream in = new InputStreamReader(file1.getInputStream(file1.getEntry(sdoesntwork)), "utf-8");
Make sure you remember to close this in a finally.

The problem is file1.getEntry(sdoesntwork) returns null because it does not find that entry.
If you are sure this name is correct, then try to use:
file1 = new ZipFile(sZipFileOld,StandardCharsets.UTF_8);

It doesn't go through your exception handler because is another type of exception, Null pointer exception is thrown because the entry is not found. You should check how or with which Charset the file has been define.

file1 = new ZipFile(sZipFileOld,StandardCharsets.UTF_8);
charset - The charset to be used to decode the ZIP entry name and comment (ignored if the language encoding bit of the ZIP entry's general purpose bit flag is set).
if the zip entry and its comment is ASCII, it is not necessary to use this way to construct the ZipFile.

Related

Reading and writing file in ISO-8859-1 encoding?

I have file encoded in ISO-8859-1. I'm trying to read it in as a single String, do some regex substitutions on it, and write it back out in the same encoding.
However, the resulting file I get always seems to be UTF-8 (according to Notepad++ at least), mangling some characters.
Can anyone see what I'm doing wrong here?
private static void editFile(File source, File target) {
// Source and target encoding
Charset iso88591charset = Charset.forName("ISO-8859-1");
// Read the file as a single string
String fileContent = null;
try (Scanner scanner = new Scanner(source, iso88591charset)) {
fileContent = scanner.useDelimiter("\\Z").next();
} catch (IOException exception) {
LOGGER.error("Could not read input file as a single String.", exception);
return;
}
// Do some regex substitutions on the fileContent string
String newContent = regex(fileContent);
// Write the file back out in target encoding
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(target), iso88591charset))) {
writer.write(newContent);
} catch (Exception exception) {
LOGGER.error("Could not write out edited file!", exception);
}
}
There is nothing actually wrong with your code. Notepad++ sees the file encoded in UTF-8 because on a basic level there is no difference between UTF-8 and the encoding you're trying to use. Only specific characters differ and some (a lot) are missing from ISO compared to UTF. You can read more here or by simply searching ISO-8859-1 vs UTF-8 in Google.
I've created a simple project with your code and tested it with characters that are different for the ISO encoding - the result is a file that IntelliJ (and probably Notepad++ as well - cannot easily check, I'm on Linux) recognizes as ISO-8859-1. Apart from that, I've added another class that makes use of new (JDK11) features from Files class. The new Scanner(source, charset) that you've used was added in JDK10, so I think that you may be using 11 already. Here's the simplified code:
private static void editFile(File source, File target) {
Charset charset = StandardCharsets.ISO_8859_1;
String fileContent;
try {
fileContent = Files.readString(source.toPath(), charset);
} catch (IOException exception) {
System.err.println("Could not read input file as a single String.");
exception.printStackTrace();
return;
}
String newContent = regex(fileContent);
try {
Files.writeString(target.toPath(), newContent, charset);
} catch (IOException exception) {
System.err.println("Could not write out edited file!");
exception.printStackTrace();
}
}
Feel free to clone the repository or check it on GitHub and use whichever code version you prefer.

File is not readable after file.setReadable(true)

I try to read the file and get FileNotFoundExeption.
File file = new File("News.out");
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
try{
in.readObject();
}
I check, that the file really exists in the directory and check "readable" property of the file.
Then I added programmatical setting of "readable" and "writable" properties
file.setReadable(true);
file.setWritable(true);
System.out.println(file.canRead());
System.out.println(file.canWrite());
And got in logs false, false.
What may be the reason of this?
EDIT:
I tried JSR 203 and use this code:
Path path = FileSystems.getDefault().getPath(filename);
try(
final InputStream in = Files.newInputStream(path);
) {
ObjectInputStream objectInputStream = new ObjectInputStream(in);
newsStorage.setEntities((ArrayList<News>) objectInputStream.readObject());
} catch (NoSuchFileException e) {
createFile(path, filename);
handleException(e);
}
And createFile() method:
private void createFile(Path path, String string) {
try {
Files.newOutputStream(path, StandardOpenOption.CREATE);
} catch (IOException e1) {
e1.printStackTrace();
}
}
File was not created.
Do I understand correctly, that
Files.newOutputStream(path, StandardOpenOption.CREATE);
should create a file?
Do yourself a favor and drop File. Use JSR 203 instead.
Try and use:
try (
final InputStream in = Files.newInputStream("News.out");
) {
// work with "in" here
}
If you can't perform the opening then you will at least have an exception telling you what exactly is wrong, something File has never been able to do.
After that, if you want to set permissions on the file, you can also do so with JSR 203 but that depends on the capabilities of the underlying filesystem. If your filesystem is POSIX compatible then you may use this method for instance. But it also may be that you cannot modify the permissions of the file either.

How can I export txt with writeObject() to a path within a string?

I have been trying to export with writeObject method but I have only achieved exporting a txt if I write literally the name (or path) of the file I want in the output directly when I call the ObjectOutputStream() method.
What I want is to call a method I have created that asks the user for the name of the file he wants to,then I concatenate it with the rest of the path were it should be located but it does´t work.
This is what I want to use:
ObjectOutputStream fpsalida = new ObjectOutputStream(new FileOutputStream(nombreArchivo()));
Intead of this that is the only way to make it work:
ObjectOutputStream fpsalida = new ObjectOutputStream(new FileOutputStream("NameOfTheFileOrCompletePath.txt"));
But I always receive the message of the catch block when executing:
When I execute the program and it tries to export the data I get the message of the catch block:
/*nombreArchivo is the String with the String returned by nombreArchivo.
Would be the same as writing FileOutputStream(nombreArchivo())); */
try {
ObjectOutputStream fpsalida = new ObjectOutputStream(new FileOutputStream(nombreArchivo)); //SERIA EL ARG NOMBREARCHIVO
fpsalida.writeObject(listaprod); //Hay que pasarle el return de la lista de prod.CREAR LA FUNC RETORNAPROD
System.out.println("\nExportado!\n");
}catch (IOException e){
System.out.println("No se ha podido exportar!\n");
}
return;
}
Here it is the part of nombreArchivo method that interests us:
System.out.println("\nWrite the name of the file you want: ");
archivoSalida += sc.nextLine() + ".txt";
System.out.println("==============================================\n");
//archivoSalida is defined as a String
return archivoSalida;
}
Thank you.
The cause of the problem was that the folder wasn´t created before.I thought the method if the directory doesn´t exist,it creates it.
The function nombreArchivo does seem to be returning an incorrect path since you are hardcoding the path instead. I would argue your hardcoded path is incorrect too, but need to see the exact error messaging to be able to tell.
I did test this example of ObjectOutputStream and seems to work fine.
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
public class SandBox {
// get absolute path from relative
public static String getPath(String relativePath){
return "/home/mack" + relativePath;
}
public static void main(String [] args){
System.out.println("Write the name of the file you want: ");
//extract filename from user
String filename = new Scanner(System.in).nextLine() + ".txt";
try {
ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream(SandBox.getPath("/" + filename)));
//write integer to stream
stream.writeInt(12345);
stream.close();
} catch (IOException ex) {
Logger.getLogger(SandBox.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Since you're not getting an IOException when you hard-code the file name, your problem is the actual content of the string being returned by nombreArchivo().
To debug the specific nature of the problem, assign the returned string to a variable, and either log it, or print it out on System.err, so you can see what it really is:
String fileName = nombreArchivo();
System.err.println("str = \"" + str + \"");
ObjectOutputStream fpsalida = new ObjectOutputStream(new FileOutputStream(fileName));
The problem will likely be obvious when you look at the error stream. You should also consider logging or printing out the exception's stack trace in the catch block:
}catch (IOException e){
e.printStackTrace();
System.out.println("No se ha podido exportar!\n");
}
I suspect fileName is either null, the empty string (""), or violates the OS's file name restrictions by (e.g.) containing illegal characters, such as line feeds.
Update: Based on your comment below, the problem is likely in how FileOutputStream calculates the file path. Try this instead, making sure that the String returned from nombreArchivo() is only the name of the file, without the directory path:
String fileName = nombreArchivo();
String filePath = "file://" + System.getProperty("user.home"); //* You may need to verify that file:// isn't already included in the user's home directory
URL url = new URL(filePath);
File directory = new File(url.toURI());
ObjectOutputStream fpsalida = new ObjectOutputStream(new
FileOutputStream(new File(directory, fileName)));
Explanation: I learned this trick from the school of hard knocks. There are subtleties in how the file path gets calculated, and this is one way I've figured out of making it work in a platform-independent fashion.

Premature end of file between File and SAXReader

I am getting this exception "Error on line -1 of document : Premature end of file. Nested exception: Premature end of file." between lines of getting path of file and reading file using SAXReader
try {
LOG.info(" start parsing ");
SAXReader reader = new SAXReader();
File myfile = new File(fileName);
if (myfile.exists()) {
document = (Document) reader.read(fileName); // getting the exception here
}
else {
LOG.error(fileName + " does not exist");
new ExceptionErrorSupport(fileName,fileName+" does not exist","ECMException",true,CONTROLLER_CONSTANTS.ECM_ERROR_DIR);
}
} catch (DocumentException e) {
e.printStackTrace();
}
It seems that File() is not yet closing then SAXReader reads the file already but I cannot find a way to close File() see Why java.io.File doesn't have a close() method?.
Are there any ways to avoid this exception?
Thanks.
It seems that File() is not yet closing
No it doesn't. File() doesn't open anything, so there is nothing to close. And even if it did it wouldn't cause this exception. Your reasoning doesn't make sense.
If you got a premature end of file, it is because your input is malformed.
This can happen because the XML file you are reading is not properly formed.
That can mean a missing end tag, or even when an end of file character is not found.

Java File.delete() does not delete all files

I have the following Java code which iterates through all the files in a directory and deletes them.
for(File file : tmpDir.listFiles())
{
file.delete();
}
It does however not delete all files. Some, usually 20-30, out of a couple of thousand, are left behind when I do this. Is it possible to fix this, or have I stumbled upon some Java voodoo that is best left alone?
It returns a boolean value, you should check that. From the JavaDoc:
Returns:
true if and only if the file or directory is successfully deleted; false otherwise
You should check the value of the return and take action.
If it returns false it may well be that you do not have permission to delete the file.
In that case you can check whether the file is writeable by the application and if not attempt to make it writeable - again this returns a boolean. If successful you can try deleting again.
You could use a utility method:
private void deleteFile(final File f) throws IOException {
if (f.delete()) {
return;
}
if (!f.canWrite() && !f.setWritable(true)) {
throw new IOException("No write permissions on file '" + f + "' and cannot set writeable.");
}
if (!f.delete()) {
throw new IOException("Failed to delete file '" + f + "' even after setting writeable; file may be locked.");
}
}
I would also take their advice in the JavaDoc:
Note that the Files class defines the delete method to throw an
IOException when a file cannot be deleted. This is useful for error
reporting and to diagnose why a file cannot be deleted.
Provided that you are using Java 7 that is. That method throws a number of exceptions that you can handle:
try {
Files.delete(path);
} catch (NoSuchFileException x) {
System.err.format("%s: no such" + " file or directory%n", path);
} catch (DirectoryNotEmptyException x) {
System.err.format("%s not empty%n", path);
} catch (IOException x) {
// File permission problems are caught here.
System.err.println(x);
}
Example taken from the Oracle tutorial page.
Forcing the garbage collector to run using System.gc(); made all the files deletable.
Make sure that you don't have any open stream like BufferedReader/Writer, FileReader/Writer etc. First close them, then you should be able to delete the file.
One more point, E.g. if you open a BufferedReader via another reader like FileReader, you must close both of the readers seperately.
So instead of this:
BufferedReader reader = new BufferedReader(new FileReader(new File(filePath)););
do this:
BufferedReader bufferedReader = null;
FileReader fileReader = null;
try{
fileReader = new FileReader(readFile);
bufferedReader = new BufferedReader(fileReader);
}catch{...}
...
try {
fileReader.close();
bufferedReader .close();
readFile.delete();
} catch (IOException e) {
e.printStackTrace();
}

Categories

Resources