Where do I need to catch IO exception from? Minecraft plugin - java

My compiler is yelling at me because of this function:
public static void writeKills() {
FileOutputStream f = new FileOutputStream(new File("plugins/core/killstats.db"));
ObjectOutputStream o = new ObjectOutputStream(f);
sKillStats.keySet().forEach(user -> o.writeObject(sKillStats.get(user)));
}
ERROR:
[ERROR] /C:/Users/lyser/git/RVAS-Core/rvas-core_v0.1.1/src/main/java/core/backend/PlayerMeta.java:[325,66] unreported exception java.io.IOException; must be caught or declared to be thrown
[ERROR] /C:/Users/lyser/git/RVAS-Core/rvas-core_v0.1.1/src/main/java/core/backend/PlayerMeta.java:[322,38] unreported exception java.io.FileNotFoundException; must be caught or declared to be thrown
[ERROR] /C:/Users/lyser/git/RVAS-Core/rvas-core_v0.1.1/src/main/java/core/backend/PlayerMeta.java:[323,32] unreported exception java.io.IOException; must be caught or declared to be thrown```
I tried throwing and catching the exception like this to no avail:
public static void writeKills() throws IOException {
FileOutputStream f = new FileOutputStream(new File("plugins/core/killstats.db"));
ObjectOutputStream o = new ObjectOutputStream(f);
try {
sKillStats.keySet().forEach(user -> o.writeObject(sKillStats.get(user)));
} catch (IOException e) {
e.printStackTrace();
}
}
Try-catching the entire method produces the same error.
I have no idea where to catch please help.

sKillStats.keySet().forEach(user -> o.writeObject(sKillStats.get(user)));
o.writeObject throws IOException, a checked exception. You need to handle that exception inside the forEach Consumer, because Consumers can't throw checked exceptions.
Either catch it inside the forEach:
.forEach(user -> {
try {
o.writeObject(sKillStats.get(user));
} catch (IOException e) {
throw new UncheckedIOException(e); // Or whatever.
}
})
or, better, write it as an enhanced for loop:
for (var user : sKillStats.keySet()) {
o.writeObject(sKillStats.get(user));
}
and then the IOException is handled by the throws IOException on the method.
Note that you can also just iterate the values() of the map, rather than iterating the keys and getting the value:
for (var value : sKillStats.values()) {
o.writeObject(value);
}
Note as well that you need to close your streams. The easiest way to do this is with try-with-resources:
try (FileOutputStream f = new FileOutputStream(new File("plugins/core/killstats.db"));
ObjectOutputStream o = new ObjectOutputStream(f)) {
// ...
}

Related

IOException that when I try to catch says will never be thrown? [duplicate]

This question already has an answer here:
What does "error: unreported exception <XXX>; must be caught or declared to be thrown" mean and how do I fix it?
(1 answer)
Closed 7 months ago.
This is my code:
#Override
public void start(Stage primaryStage) throws FileNotFoundException {
System.out.print("Url gui successfully started.");
final HBox hBox = new HBox();
hBox.setSpacing(5);
final TextField urlTextField = new TextField();
urlTextField.setPromptText("Type Url Here");
Button unblock = new Button("Unblock");
Button block = new Button("Block");
String hostsFile = BlockAndUnblock.getHostsFile();
String blockedUrls = BlockAndUnblock.getBlockedUrls();
boolean inSession = InSession.inSession > 0;
try {
unblock.setOnAction(event -> BlockAndUnblock.blockSite(hostsFile,blockedUrls,urlTextField.getText(), inSession));
block.setOnAction(event -> BlockAndUnblock.unBlockSite(hostsFile,blockedUrls,urlTextField.getText(), inSession));
} catch (IOException e) {
e.printStackTrace();
System.out.println("You encountered an IOException when trying to initiate the block and unblock buttons.");
}
ArrayList<String> urls = new ArrayList<String>();
urls = readUrls();
ListView listView = new ListView();
listView.setId("Listview");
for (String s: urls) {
listView.getItems().add(s);
}
hBox.getChildren().add(listView);
hBox.getChildren().add(urlTextField);
hBox.getChildren().add(block);
hBox.getChildren().add(unblock);
hBox.setAlignment(Pos.CENTER_LEFT);
hBox.setId("Urls");
Scene scene = new Scene(hBox, 750, 500);
scene.getStylesheets().addAll(this.getClass().getResource("../style.css").toExternalForm());
primaryStage.setTitle("Urls");
primaryStage.setScene(scene);
primaryStage.show();
}
The block and unblock methods it calls are these:
public static void unBlockSite(String hostsFile, String blockedUrls, String url, boolean inSession) throws IOException {
String file = Files.readString(Paths.get(hostsFile));
file = file.replace("0.0.0.0 " + url.substring(url.indexOf("//") + 2,url.length()-1) +"\n","");
file = file.replace("::0 " + url.substring(url.indexOf("//") + 2,url.length()-1) +"\n","");
Files.writeString(Paths.get(blockedUrls), file, StandardOpenOption.TRUNCATE_EXISTING);
if (inSession) {
unBlock(hostsFile);
block(hostsFile, blockedUrls);
}
}
public static void blockSite(String hostsFile, String blockedUrls, String url, boolean inSession) throws IOException {
if (inSession) unBlock(hostsFile);
Files.writeString(Paths.get(blockedUrls), "0.0.0.0 " + url.substring(url.indexOf("//") + 2,url.length()-1) +"\n", StandardOpenOption.APPEND);
Files.writeString(Paths.get(blockedUrls), "::0 " + url.substring(url.indexOf("//") + 2,url.length()-1) +"\n", StandardOpenOption.APPEND);
if (inSession) block(hostsFile, blockedUrls);
}
This is the error I'm getting:
site\java\BlockUrlsMenu.java:37: error: unreported exception IOException; must be caught or declared to be thrown
unblock.setOnAction(event -> BlockAndUnblock.blockSite(hostsFile,blockedUrls,urlTextField.getText(), inSession));
^
site\java\BlockUrlsMenu.java:38: error: unreported exception IOException; must be caught or declared to be thrown
block.setOnAction(event -> BlockAndUnblock.unBlockSite(hostsFile,blockedUrls,urlTextField.getText(), inSession));
^
site\java\BlockUrlsMenu.java:39: error: exception IOException is never thrown in body of corresponding try statement
} catch (IOException e) {
^
3 errors
What confuses me is that apparently BlockAndUnblock require me to catch or throw the IOException beforehand, but when I surround them in a try{} catch{} method it says they'll never throw an IOException. I also tried putting all the content of the start() method into a try{} catch{} block and it still gave me the first two errors.
Why is it telling me to catch an IOException and then saying it won't throw one?
Thanks for the help, I know this is a lot of code to go over.
It's a lot of code so my analysis may be superficial, but I think it happens because .setOnAction() takes a Lambda expression.
Lambdas can't throw checked exceptions like IOException (hence the catch block becomes invalid and you get the third error, since the two lambdas can't actually throw), but at the same time your lambdas are calling two functions which throw themselves an IOException and you're not catching them inside the lambda (so you get the first and second error).
Try to change this:
try {
unblock.setOnAction(event - > BlockAndUnblock.blockSite(hostsFile, blockedUrls, urlTextField.getText(), inSession));
block.setOnAction(event - > BlockAndUnblock.unBlockSite(hostsFile, blockedUrls, urlTextField.getText(), inSession));
} catch (IOException e) {
e.printStackTrace();
System.out.println("You encountered an IOException when trying to initiate the block and unblock buttons.");
}
... into this:
try {
unblock.setOnAction(event - > {
try {
BlockAndUnblock.blockSite(hostsFile, blockedUrls, urlTextField.getText(), inSession));
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
block.setOnAction(event - > {
try {
BlockAndUnblock.unBlockSite(hostsFile, blockedUrls, urlTextField.getText(), inSession));
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
} catch (RuntimeException e) {
e.printStackTrace();
System.out.println("You encountered an IOException when trying to initiate the block and unblock buttons.");
}
With the above, inside each lambda you catch IOException and you wrap it inside a RuntimeException (which is unchecked so can be thrown by the lambda).
In the outer catch, you catch the RuntimeException and do whatever you wanted to do initially with the IOException

How to properly catch exceptions with java file I/O [duplicate]

This question already has answers here:
Closing a Java FileInputStream
(9 answers)
Closed 5 years ago.
I'm trying to become familiar with file I/O in Java. I started off by getting a lot of errors when compiling, such as error: unreported exception IOException; must be caught or declared to be thrown. So I made some changes to the code and ended up with:
public static void main(String[] args){
FileInputStream in = null;
FileOutputStream out = null;
String content = "hello";
byte[] contentBytes = content.getBytes();
try{
out = new FileOutputStream("output.txt");
out.write(contentBytes);
}catch(IOException e){
}catch(FileNotFoundException e){
}
finally{
if (out != null)
out.close();
}
}
Still, I get this error:
FileIO.java:16: error: exception FileNotFoundException has already been caught
}catch(FileNotFoundException e){
^
FileIO.java:21: error: unreported exception IOException; must be caught or declared to be thrown
out.close();
^
2 errors
Where did I "already catch" FileNotFoundException?
Because of the second error, do I need to put another try and catch statement in the finally clause to catch IOException? That seems messy and over-complicated. Am I doing something else wrong? And why doesn't java let me do what I want without forcing me to catch exceptions?
EDIT:
If I do:
public static void main(String[] args){
FileOutputStream out = null;
String content = "hello";
byte[] contentBytes = content.getBytes();
try{
out = new FileOutputStream("output.txt");
out.write(contentBytes);
}catch(FileNotFoundException e){
}catch(IOException e){
}
finally{
if (out != null)
out.close();
}
}
I get:
FileIO.java:20: error: unreported exception IOException; must be caught or declared to be thrown
out.close();
^
1 error
Where did I "already catch" FileNotFoundException?
FileNotFoundException extends IOException, which means IOException can catch FileNotFoundException exception. So, there is no point of FileNotFoundException after it.
Just reverse the order, to resolve this issue.
}catch(FileNotFoundException e){
}catch(IOException e){
}
Also, don't leave catch block blank, use them to display appropriate message, else you won't have any clue, if you got any exception.
second error, do I need to put another try and catch statement in the finally clause to catch IOException?
Yes. But, I would suggest to use try-with-resource it will take care of closing resource at the end.
As said, you should use try-with-resource instead
try (FileOutputStream out = new FileOutputStream("people.bin");)
{
out.write(contentBytes);
}
catch(FileNotFoundException e)
{
}catch(IOException e){
}
I am not really sure how the compiler let you the code. Could you please try the below code. I dont have any error when i run it.
Answer to the first question is :
Either remove FileNotFoundException line or put it above IOexception.
Answer to the second question is :
if you think that is messy, you can just duck the exception by using Throws i.e. throws IOException next to main(String[] args).
Java(compiler) pushes you to catch or declare your exceptions(using throws) because, the main purpose of Exceptions in java is not running into errors when the code is run. When an exception happens in the finally block, it leads to error and it ultimately impacts your application at run time. Have to very careful when you are closing stuff in Finally block. If you think, the code looks messy, then you can use Throws key word which solves your concern.
public static void main(String[] args){
FileInputStream in = null;
FileOutputStream out = null;
String content = "hello";
byte[] contentBytes = content.getBytes();
try{
out = new FileOutputStream("output.txt");
out.write(contentBytes);
}catch(IOException e){
}
finally{
if (out != null){
try{
out.close();
}catch(IOException e){
}
}
}
}
String outputPath = "output.txt";
String content = "hello";
byte[] contentBytes = content.getBytes();
try (FileOutputStream out = new FileOutputStream(outputPath)) {
out.write(contentBytes);
} catch (FileNotFoundException e) {
System.err.println("Failed to find the file to write to: " + outputPath);
} catch (IOException e) {
System.err.println("Failed to write to file: " + outputPath);
}
As QuakeCore mentioned FileNotFoundEception extends IOException, this is why you should catch FileNotFoundEception first.
It is a good practice to print at least some message, so you will not be surprised when there is no output and no exceptions in console / logs.
FileOutputStream implements AutoClosable interface. This why it is better to use try with resources. In this case JVM will close it automatically.
public static void main(String[] args) throws IOException{
FileOutputStream out = null;
String content = "hello";
byte[] contentBytes = content.getBytes();
try{
out = new FileOutputStream("output.txt");
out.write(contentBytes);
}catch(FileNotFoundException e){
}
finally{
if (out != null)
out.close();
}
}
Since FileNotFoundException extends IOException, then just by catching IOException you are catching all subtypes of IOException.
And regarding your second question, since `.close()` method also throws `IOException`, you can put all the IO code in a method, and have that method to throw `IOException`, then the caller can deal with the any exceptions.
for example:
private static void writeToFile() throws IOException{
FileInputStream in = null;
FileOutputStream out = null;
String content = "hello";
byte[] contentBytes = content.getBytes();
try{
out = new FileOutputStream("output.txt");
out.write(contentBytes);
}finally{
if (out != null)
out.close();
}
}
and then your main would look like this.
public static void main(String[] args){
FileInputStream in = null;
FileOutputStream out = null;
String content = "hello";
byte[] contentBytes = content.getBytes();
try{
writeToFile();
}catch(IOException e){
}
}
And have a look at tryResourceClose

AccessDeniedException exception in java

I have the following code where I need to catch AccessDeniedException exception
import java.io.PrintWriter;
import java.io.IOException;
import java.nio.file.AccessDeniedException;
class MyFileClass {
public void write()
throws IOException
{
PrintWriter out = new PrintWriter("sample.txt");
out.printf("%8.2f\n", 3.4);
out.close();
}
}
public class MyClass {
public static void main(String[] args)
throws Exception
{
try {
MyFileClass mf = new MyFileClass();
mf.write();
} catch (AccessDeniedException e) {
print("Access denided");
}
catch (FileNotFoundException e) {
print("File not found");
}
}
}
In case sample.txt is read only, I get output as "file not found" rather "Access denided". I would like to understand what is the reason for this? Also, is the above structure for catching AccessDeniedException correct?
AccessDeniedException is only thrown by the new file API; the old file API (which you use with this PrintWriter constructor) only knows how to throw FileNotFoundException even if the real filesystem-level problem is not "the file does not exist".
You have to use the new API to open an output stream to the destination file; then you can have meaningful exceptions:
// _will_ throw AccessDeniedException on access problems
final OutputStream out = Files.newOutputStream(Paths.get(filename));
final PrintWriter writer = new PrintWriter(out);
More generally, the new file API defines FileSystemException (inheriting IOException), which all new, meaningful exceptions defined by the new API inherit.
This means among other things that you can clearly separate, in catch clauses, what is caused by filesystem-level errors and "real" I/O errors, which you can't do with the old API:
try {
// some new file API operation
} catch (FileSystemException e) {
// deal with fs error
} catch (IOException e) {
// deal with I/O error
}
There is NO such AccessDeniedException in PrintWriter.
SecurityException is the exception thrown by PrintWriter
If a security manager is present and checkWrite(file.getPath()) denies
write access to the file

Try and catch blocks: whether in the class itself or when I call the method outside the class

Could you help me understand where should I throw exceptions and catch them.
Please, have a look at my code. I thought that in Thrd class I have already thrown and caught the exception. But when I wrote in the main class FirstThread.readFile("ParallelProgramming.txt");, I faced a runtime error - unhandled exception. So, I had to use try and catch. So, I somehow can't understand why in the Thd class my try and catch blocks didn't work.
package parallelprogramming;
import java.lang.Thread;
import java.io.*;
public class Thrd extends Thread {
public void readFile(String File) throws FileNotFoundException {
FileReader fr = new FileReader(File);
BufferedReader br = new BufferedReader(fr);
String s;
try {
while ((s = br.readLine()) != null) {
System.out.println(s);
}
fr.close();
}
catch (FileNotFoundException FNFD) {
System.out.println("File not found!");
}
catch (IOException IOE){
System.out.println("IOException caught!");
}
}
}
package parallelprogramming;
import java.io.FileNotFoundException;
public class ParallelProgramming {
public static void main(String[] args) throws FileNotFoundException {
Thrd FirstThread = new Thrd();
try {
FirstThread.readFile("ParallelProgramming.txt");
} catch (FileNotFoundException FNFD) {
System.out.println("File not found!");
}
}
}
The rules with checked exceptions (and this includes IOException, which FileNotFoundException is a child of), are as follows:
if you cannot, or do not want, to handle it in your current method, declare that the method throws it;
if you want to handle it in your current method, then catch it; note that even in this case you can rethrow that exception;
if main() throws any exception, and this exception triggers, the program terminates.
Now, we suppose that you are using Java 7. In this case, do that:
public void readFile(final String file)
throws IOException
{
final Path path = Paths.get(file);
for (final String line: Files.readAllLines(path, StandardCharsets.UTF_8))
System.out.println(line);
}
Why bother? ;)
If you don't want to do that but read line by line, then:
public void readFile(final String file)
throws IOException
{
final Path path = Paths.get(file);
try (
final BufferedReader reader = Files.newBufferedReader(path,
StandardCharsets.UTF_8);
) {
String line;
while ((line = reader.readLine()) != null)
System.out.println(line);
}
}
The second form is preferred if you wish to treat exceptions specifically. Note that with Java 7, you have meaningful exceptions as to why you cannot access the file vs IOException: NoSuchFileException, AccessDeniedException, etc etc. All these inherit FileSystemException. The old file API can't do that for you.
This means that if you want to deal with filesystem level errors you can do:
catch (FileSystemException e) { /* ... */ }
where before that you did:
catch (FileNotFoundException e) { /* ... */ }
Translated to the code above, if you want to catch exceptions you'll then do:
// All exceptions handled within the method -- except if you rethrow it
public void readFile(final String file)
{
final Path path = Paths.get(file);
try (
final BufferedReader reader = Files.newBufferedReader(path,
StandardCharsets.UTF_8);
) {
String line;
while ((line = reader.readLine()) != null)
System.out.println(line);
} catch (FileSystemException e) {
// deal with a filesystem-level error
// Note that you MUSt catch it before IOException
// since FileSystemException inherits IOException
} catch (IOException e) {
// deal with a low-level I/O error
}
}
Remove 'throws FileNotFoundException' from the readFile method of class Thrd then you dont need to handle this exception in main method of class ParallelProgramming.
As you throw FileNotFoundException from readFile method then exception will pass to the method will called this i.e. then main method need to handle this exception.
There are two ways to handle an exception either you need to catch it or throw it again.
In the readFile method you have done both. you caught the exceptions using catch blocks then you have mentioned that readFile method throws FileNotFoundException, so when ever you use readFile method you need to catch the exception again.

Android: Unhandled exception type IOException Error

I am total noob at Android dev. I am still learning, and I am on very first step of my app dev.
I have this code working and it runs fine or regular Java, now I am trying to implement to Android OS.
In my code where it says TEST.openStream() I get Unhandled exception type IOException error.
package com.zv.android;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import android.app.Activity;
import android.os.Bundle;
public class ZipActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
URL TEST = new URL("http://www.google.com/");
BufferedReader in = new BufferedReader(new InputStreamReader(TEST.openStream()));
String inputLine;
int line=0;
while ((inputLine = in.readLine()) != null){
line++;
//System.out.println(line + "\t" + inputLine);
}
// in.close();
} catch(MalformedURLException e) {
//Do something with the exception.
}
}
}
Error message is simple: you need to catch the IOException, this because URL.openStream() is declared as
public final InputStream openStream() throws IOException
so by accepting the contract of the method you also accept the fact that you must handle this exception, this is how it works in Java. This is a checked exceptions, then it must be caught because this kind of exceptions represent situations that may arise and that your code must handle.
To catch it just add another case in your try statement:
try {
..
catch (MalformedURLException e) {
..
}
catch (IOException e) {
..
}
Just as a final note: you don't need to catch it when you call the openStream() method, you could state that the method that calls openStream() will forward the exception to the caller but in the end of the call chain you will have to catch it in any case.
Catch IOException also, like how you did for MalformedURLException (or) declare method as throws IOException.
try {
URL TEST = new URL("http://www.google.com/");
BufferedReader in = new BufferedReader(new InputStreamReader(TEST.openStream()));
String inputLine;
int line=0;
while ((inputLine = in.readLine()) != null){
line++;
//System.out.println(line + "\t" + inputLine);
}
// in.close();
} catch(MalformedURLException e) {
//Do something with the exception.
} catch(IOException e2) {
//Do something with the exception.
}
IOException is checked exception, which either need to be catch (or) re-throw. See this tutorial for more information.
You need to catch IOException because openStream() method may throw IOException in abnormal case.
TEST.openStream()
might throw an IOException which is a checked exception in java, thus you have to either Handle the IOException using try/catch blocks or declare IOException in your method signature using throws clause.
you have to handle IOException in your catch block .
try {
URL TEST = new URL("http://www.google.com/");
BufferedReader in = new BufferedReader(new InputStreamReader(TEST.openStream()));
//rest of your code
} catch(MalformedURLException e) {
//Do something with the exception.
}
catch(MalformedURLException e) {
//Do something with the exception.
}
catch(IOException ex) {
ex.printStackTrace();
}
Declaring IOException in your method signature:
public void onCreate(Bundle savedInstanceState) throws IOException {
in this case you dont wrap your code inside a try/catch, although i would strongly recommend always handle the exception using try/catch rather than declaring it using throws clause.

Categories