Java ImageIO: Exception Weirdness - java

In my application I was trying to save a BufferedImage to a PNG file using ImageIO. The file is chosen by the user so I need to react to errors that might happend (e.g. user tries to save in a location he has no write permission for). However I am unable to catch the IOException that occurs.
The following code shows the problem. Trying to save to "/foo" should throw an exception for most users on *nix systems, since they do not have write permission in the root directory.
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class IOTest {
public static void main(String[] args) {
BufferedImage img = new BufferedImage(640, 480,
BufferedImage.TYPE_INT_RGB);
try {
File f = new File("/foo");
ImageIO.write(img, "png", f);
} catch (IOException e) {
System.out.println("Caught IOException!");
}
}
}
However, the exception is not caught. Output:
java.io.FileNotFoundException: /foo (Permission denied)
at java.io.RandomAccessFile.open(Native Method)
at java.io.RandomAccessFile.<init>(RandomAccessFile.java:233)
at javax.imageio.stream.FileImageOutputStream.<init>(FileImageOutputStream.java:69)
at com.sun.imageio.spi.FileImageOutputStreamSpi.createOutputStreamInstance(FileImageOutputStreamSpi.java:55)
at javax.imageio.ImageIO.createImageOutputStream(ImageIO.java:419)
at javax.imageio.ImageIO.write(ImageIO.java:1530)
at IOTest.main(IOTest.java:16)
Exception in thread "main" java.lang.NullPointerException
at javax.imageio.ImageIO.write(ImageIO.java:1538)
at IOTest.main(IOTest.java:16)
Note that FileNotFoundException is a subclass of IOException so it should get caught. A second catch block did not help either:
catch (FileNotFoundException e) {
System.out.println("Caught FileNotFoundException!");
} catch (IOException e) {
System.out.println("Caught IOException!");
}
What am I doing wrong?

It stems from the details of ImageIO implementation. You will circumvent the problem if you don't pass the File instance to ImageIO.write, but first try to open a FileOutputStream yourself and pass that to write.
This is a more precise analysis of what happens in ImageIO.write. Line 1530:
stream = createImageOutputStream(output);
Line 1538:
stream.close();
And if you take a look at the implementation of createImageOutputStream, you'll see several code paths that return null.

It looks like the ImageIO.write method prints the IOException but really doesn't handle it and ends with a NullPointerException. In this specific case of a buggy library, maybe you should catch any RuntimeException...
Of course it will be better to test before if the directory exists and is writable.

It seems that ImageIO.write() wraps the FileNotFoundException into a NullPointerException.
You should catch NullPointerException, or better check file existence before invoking ImageIO.write().

By the looks of it the FileNotFoundException is being handled within javax.imageio.ImageIO.write and that failure is causing a null pointer exception. Try to check the file permissions before you try saving it!

Related

How to throw my own Exception with a pre written method in Java?

I have written my own Exception but I can't throw it.
The application still terminates and gives me the standard error Message:
Exception in thread "main" java.nio.file.NoSuchFileException: H:\db_sort\pdfs\test_5_database
at sun.nio.fs.WindowsException.translateToIOException(Unknown Source)
at sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
at sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
at sun.nio.fs.WindowsFileCopy.move(Unknown Source)
at sun.nio.fs.WindowsFileSystemProvider.move(Unknown Source)
at java.nio.file.Files.move(Unknown Source)
at ExceptionTest.filemove(ExceptionTest.java:22)
at ExceptionTest.main(ExceptionTest.java:9)
The application has to move some files but it could be that the file that should be moved isn't existing. Then the program shall just print out that the file couldn't be moved and then the program shall move on to the next file.
Here is a piece of my code in which I want to throw the Exception.
The file test_5_database isn't existing. Then it shall just print out:
The File has been renamed, moved or deleted and those changes are not synchronized with the database.
Here is my code (I am not posting my whole code, I will just post my Exception problem):
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class ExceptionTest {
public static void main(String[] args) throws IOException {
try {
filemove();
System.out.println("The file has been moved!");
}
catch(NoSuchFileException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
private static void filemove() throws IOException, NoSuchFileException{
Files.move(Paths.get("H:/db_sort/pdfs/test_5_database"),Paths.get("H:/db_sort/pdf s/2019-08/test_5_database"));
}
}
class NoSuchFileException extends Exception{
NoSuchFileException(){
super("The file has been moved, renamed or deleted and those changes
are not synchronized with the database");
}
}
I hope that someone can help me and can explain me how I can throw my own Error Message. After displaying the error message the application shall continue with moving files.
Sorry if I made some stupid mistakes in my code, I am quite new to the topic. English is not my mother tongue so please excuse any grammatical or spelling mistakes.
I hope you have a nice day.
The method Files.move(...) throws a NoSuchFileException which comes from the package java.nio.file.
Your implementation of NoSuchFileException may have the same name, but it is never thrown. So you have to catch the java.nio.file.NoSuchFileException and throw your own my.package.NoSuchFileException.
But maybe it is best (to avoid all confusion) to rename your Exception in for example FileNotSynchronizedException. You could do it like this:
First option (you may want to remove the imports for NoSuchFileException)
private static void filemove() throws IOException, NoSuchFileException{
try{
Files.move( Paths.get("H:/db_sort/pdfs/test_5_database"),Paths.get("H:/db_sort/pdf s/2019-08/test_5_database"));
}catch(java.nio.file.NoSuchFileException e){
throw new my.package.NoSuchFileException();
}
}
Second Option
private static void filemove() throws IOException, FileNotSynchronizedException{
try{
Files.move( Paths.get("H:/db_sort/pdfs/test_5_database"),Paths.get("H:/db_sort/pdf s/2019-08/test_5_database"));
}catch(NoSuchFileException e){
throw new my.package.FileNotSynchronizedException();
}
}
See the the different throws clause in the method header? You simply changed the Exception by throwing your own.
IMHO the second option is better, you would avoid conflicts with the existing Exceptions from java.nio.files and it gives you the opportunity to make more specific exceptions. For example if you want to catch the IOException as well and throw your own, then just add another catch clause.
If you create new exception give it name different from the existing one.
To thorow exception you should write:
throw new ExceptionName("message");
for example:
throw new UnsupportedOperationException();
If you want to throw exception when file does not exist:
if(checkIfFileExists) {
throw new ExceptionName("message");
}
before you perform operation.
In your case the best approach is to change catch (creating new exception is unnecessary in that case), for example:
catch(NoSuchFileException e) {
System.out.println("The file has been moved, renamed or deleted and those
changes are not synchronized with the database");
System.out.println(e.getMessage());
e.printStackTrace();
}
You can throw a custom exception like below, hope my understanding is correct.
package test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class ExceptionTest {
public static void main(String[] args) throws NoSuchFileException {
try {
filemove();
System.out.println("The file has been moved!");
}
catch(IOException e) {
throw new NoSuchFileException();
}
}
private static void filemove() throws IOException{
Files.move(Paths.get("H:/db_sort/pdfs/test_5_database"),Paths.get("H:/db_sort/pdf s/2019-08/test_5_database"));
}
}
class NoSuchFileException extends Exception{
NoSuchFileException(){
super("The file has been moved, renamed or deleted and those changes are not synchronized with the database");
}
}
Output :
Exception in thread "main" test.NoSuchFileException: The file has been moved, renamed or deleted and those changes are not synchronized with the database
at test.ExceptionTest.main(ExceptionTest.java:15)

Why does the Formatter(String fileName) constructor not work without handling FileNotFoundException? [duplicate]

This question already has answers here:
What are checked exceptions in Java/C#?
(3 answers)
Closed 4 years ago.
The constructor Formatter(String fileName) doesn't seem to compile when I don't handle FileNotFoundException even if the file already exists.
Here's the code that works:
import java.util.*;
public class CreatingFiles {
public static void main(String[] args) {
final Formatter MYFILE;
try {
MYFILE = new Formatter("john.txt");
System.out.println("File created");
}
catch (Exception e) {
System.out.println("Error!");
}
}
}
However when I remove the try/catch block:
import java.util.*;
public class CreatingFiles {
public static void main(String[] args) {
final Formatter MYFILE;
MYFILE = new Formatter("john.txt");
}
}
The compiler tells me that I have to either throw or catch the exception. So why doesn't it work without handling the exception?
The constructor Formatter(String) [https://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#Formatter(java.lang.String)], throws a FileNotFound exception [https://docs.oracle.com/javase/7/docs/api/java/io/FileNotFoundException.html], a checked exception [https://en.wikibooks.org/wiki/Java_Programming/Checked_Exceptions], so you have to catch it or re-throw it.
https://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#Formatter(java.lang.String)
SecurityException - If a security manager is present and checkWrite(fileName) denies write access to the file
FileNotFoundException - If the given file name does not denote an existing, writable regular file and a new regular file of that name cannot be created, or if some other error occurs while opening or creating the file
Compiler don't know if the file exist. It will find only at execution.
You can put throws ExceptionName in method declaration
public void MyMethod() throws ExceptionName{
//TODO
}
but will be throwed to the caller of this method.
A FileNotFoundException is a checked exception, meaning that you must be able to recover from it, i. e. display a message like The file could not be opened. Users frequently delete files, hence, you cannot be sure that the file you are requesting actually exists. However, it would be a really bad experience for the user if your application crashed only due to the file not being present.
For that reason, the compiler forces you to handle the case that the file you are requesting does not exist. Most probably, you should only display some kind of error message to the user and log the exception maybe.
I found this explanation of checked exceptions to be very helpful in case you have further questions.

Android unreported exception IOException error

I am new to android apps development. Recently,Im writing an application which able to show public ip based on Ipify. So far, i already:
Download the required jar file and put inside libs folder
I also compile file within gradle
Then i import required class it to my class
How to use Ipify, according to its website:
import org.ipify.Ipify;
public class HelloIP {
public static void main(String[] args) throws IOException {
System.out.println(Ipify.getPublicIp());
}
}
I write the following method to be invoked from another class:
public static String getPublicIp() throws IOException{
String ip = Ipify.getPublicIp();
return ip;
}
Another Class
//Get wifi
getWifiName wifiInfo = new getWifiName();
String myIP = wifiInfo.getPublicIp();
However, i keep getting:
Error:(52, 43) error: unreported exception IOException; must be caught
or declared to be thrown
I tried to modify the code and use the following try and catch, but still got the same error.
public static String getPublicIp() throws IOException{
String myip = Ipify.getPublicIp();
try{
return myip;
}
catch (IOException e){
System.out.println("General I/O exception: " + e.getMessage());
e.printStackTrace();
}
}
Im not too good in catch and throw exception, and already spent the whole day for this.I dont have idea anymore to fix this error..T.T
public static String getPublicIp() {
try{
return Ipify.getPublicIp();
}catch (IOException e){
System.out.println("General I/O exception: " + e.getMessage());
e.printStackTrace();
}
return null;
}
In case it didn't help, clean project in your IDE. You may have some data cached and it might be a reason.
Your problem is in another class! As you have declared the method getPublicIp() to throw IOException that class is afraid of receiving the Exception and therefor requests catching it.
In Java you have two types of Exceptions. Checked and unchecked. Checked Exceptions must be caught.
In Java Exceptions are used for marking unexpected situations. For example parsing non-numeric String to a number (NumberFormatException) or calling a method on a null reference (NullPointerException). You can catch them in many ways.
Unchecked Exceptions are those which extend RunTimeException. They are used for marking unexpected states usually caused by user's input. They shouldn't cause harm and should be worked out with business logic. You don't have to catch them, but sometimes you should.
On the other hand there are Checked Exceptions which mark dangerous situations. For example the application being unable to open a file. As those situations are found dangerous, you must catch them.
try{
//some code
} catch (NumberFormatException e1) {
e.printStackTrace() //very important - handles the Exception but prints the information!
} catch (NullPointerException e2) {
e.printStackTrace();
}
or using the fact, that they all extend Exception:
try {
//somecode
} catch (Exception e) {
e.printStackTrace;
};
or since Java 7:
try {
//somecode
} catch (NullPointerException | NumberFormatException e) {
e.printStackTrace;
};

How to reliably detect that an atomic move of a directory failed because the target already exists

In a server, I am initializing the working directory for a resource on first access to the resource. There may be parallel requests for the resource handled by multiple processes of the server, which means that I need to take care that none of the processes sees a partially initialized working directory. The solution for this is initialize the working directories in a temporary, sibling directory and then move it to its final location with Files.move and the StandardCopyOption.ATOMIC_MOVE.
In case two processes initialize a working directory at the same time, the second atomic move fails. This is not really a problem because then the working directory is initialized correctly, so the process that came in second only needs to discard the temporary directory it created and continue.
I tried to do this with the following code:
private void initalizeWorkDirectory(final Resource resource) throws IOException {
File workDir = resource.getWorkDirectory();
if (!workDir.exists()) {
File tempDir = createTemporarySibligDirectory(workDir);
try {
fillWorkDirectory(tempDir, resource);
Files.move(tempDir.toPath(), workDir.toPath(), StandardCopyOption.ATOMIC_MOVE);
} catch (FileAlreadyExistsException e) {
// do some logging
} finally {
FileUtils.deleteQuietly(tempDir);
}
}
}
However I noticed, that only catching the FileAlreadyExistsException doesn't seem enough. In case of a move collision, there are also other exceptions thrown. I don't just want to catch all exceptions because this could be hiding real problems.
So isn't there a way to reliably detect from the exception thrown by Files.move that an atomic move of a directory failed because the target directory already existed?
From observing the exceptions and by looking at the FileSystemProvider implementations for Windows and Linux, we found out the following:
On Windows, an AccessDeniedException is thrown when trying to move a directory to an existing directory.
On Unix (and its relatives), a generic FileSystemException is thrown with a message that corresponds to the errno.h constant ENOTEMPTY.
When programming against these implementation details, one can reasonably well detect directory move collisions without too much danger of hiding other problems.
The following code implements an atomic move which always throws a FileAlreadyExistsException in case of a move collision:
import java.io.File;
import java.io.IOException;
import java.nio.file.AccessDeniedException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.FileSystemException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
public class AtomicMove {
private static final String ENOTEMPTY = "Directory not empty";
public static void move(final File source, final File target) throws FileAlreadyExistsException, IOException {
try {
Files.move(source.toPath(), target.toPath(), StandardCopyOption.ATOMIC_MOVE);
} catch (AccessDeniedException e) {
// directory move collision on Windows
throw new FileAlreadyExistsException(source.toString(), target.toString(), e.getMessage());
} catch (FileSystemException e) {
if (ENOTEMPTY.equals(e.getReason())) {
// directory move collision on Unix
throw new FileAlreadyExistsException(source.toString(), target.toString(), e.getMessage());
} else {
// other problem
throw e;
}
}
}
}

Possible bug with load() and parse() methods in PDFBox?

I tried to use PDFBox on regular .pdf files and it worked fine.
However when I encountered a corrupted .pdf , the code would "freeze" .. not throwing errors or something .. simply the load or parse function take forever to execute
Here is the corrupted file (i have zipped it so that everybody could download it), it is probably not a native pdf file but it was saved as a .pdf extension and it is only 4 Kb.
I am not an expert at all, but I think that this is a bug with PDFBox. According to documentation, both load() and parse() methods are supposed to throw exceptions if they fail. However in case with my file, the code would take forever to execute and not throw exception.
I tried using only load, one can try parse() .. the result is the same
import java.io.FileNotFoundException;
import java.io.IOException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.util.PDFTextStripper;
public class TestTest {
public static void main(String[] args) throws FileNotFoundException, IOException {
System.out.println(pdfToText("C:\\..............MYFILE.pdf"));
System.out.println("done ! ! !");
}
private static String pdfToText(String fileName) throws IOException {
PDDocument document = null;
document = PDDocument.load(new File(fileName)); // THIS TAKES FOREVER
PDFTextStripper stripper = new PDFTextStripper();
document.close();
return stripper.getText(document);
}
}
How to force this code throw an exception or stop executing if the .pdf file is corrupted?
Thanks
Try this solution:
private static String pdfToText(String fileName) {
PDDocument document = null;
try {
document = PDDocument.load(fileName);
PDFTextStripper stripper = new PDFTextStripper();
return stripper.getText(document);
} catch (IOException e) {
System.err.println("Unable to open PDF Parser. " + e.getMessage());
return null;
} finally {
if (document != null) {
try {
document.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
For implementing simple timeouts for 3rd party libs I often use an implementation like Apache Commons ThreadMonitor:
long timeoutInMillis = 1000;
try {
Thread monitor = ThreadMonitor.start(timeoutInMillis);
// do some work here
ThreadMonitor.stop(monitor);
} catch (InterruptedException e) {
// timed amount was reached
}
Example code is from Apache's ThreadMonitor Javadoc.
I only use this when the 3rd party API does not provide some timeout mechanism, of course.
However I was forced to tweak this a bit some weeks ago, because this solution does not work well with (3rd party) code that is using Exception masking.
In particular we run into problems with c3p0 which masks all Exceptions (and in particular InterruptedExceptions). Our solution was to tweak the implementation to also check the exception's cause chain for InterruptedExceptions.

Categories

Resources