how to return FileInputStream ?? in java [duplicate] - java

This question already has answers here:
Java return value (in try/catch clause)
(6 answers)
Closed 2 years ago.
package asasaSASA;
import java.io.*;
class FileInputTest {
public static FileInputStream f1(String fileName) {
try {
FileInputStream fis = new FileInputStream(fileName);
System.out.println("f1: File input stream created");
return fis; // I HAVE RETURN fis
}
catch (FileNotFoundException e) {
System.out.println("에러는"+e);
}
}
public static void main(String args[]) {
FileInputStream fis1 = null;
String fileName = "foo.bar";
System.out.println("main: Starting " + FileInputTest.class.getName()
+ " with file name = " + fileName);
fis1 = f1(fileName);
System.out.println("main: " + FileInputTest.class.getName() + " ended");
}
}
I want to make this code run but it said
This method must return a result of type FileInputStream
I can't understand because I made return fis. Why does it say that you have to return? I already returned it!

FileInputStream fis = new FileInputStream(fileName);
If the above line throws a FileNotFoundException then the next line of your code that will be executed is
System.out.println("에러는"+e);
which means it bypasses your return statement and that's why you are getting the compiler error.
There are many different ways to fix the compiler error and the other answers explain the different ways. I'm just answering your question, namely
Why does it say that you have to return?
I hope you understand now why you are wrong when you say
I already returned it!

Your exception handling is the problem. It's common, but bad code style: Whenever you catch an exception, the right move is to either deal with that exception, or, to ensure that you (re)throw some exception.
Log it, or print it? That is not handling an exception.
In this case, 'file not found' is not something you can be expected to handle; not unless you expand on what f1 is supposed to do (tip: Methods should be a bit more descriptive than that). Thus, throwing something is fair game. Furthermore, the very definition of f1 (presumably; that name is not particular enlightening and the method has no documentation) suggests that 'open this file' is a fundamental aspect of it, and therefore, throwing a FileNotFoundException is fair as well.
Thus:
Best solution
public static FileInputStream f1(String fileName) throws IOException {
FileInputStream fis = new FileInputStream(fileName);
System.out.println("f1: File input stream created");
return fis;
}
public static void main(String[] args) throws Exception {
String fileName = "foo.bar";
System.out.println("main: Starting " + FileInputTest.class.getName()
+ " with file name = " + fileName);
try (InputStream in = f1(fileName)) {
// you must close any resources you open using a try-with-resources
// construct; you did not do that in your code, I fixed this.
}
}
NB: your psv main can (and generally should!) be declared to throws Exception.
Alternate take
This one works in any scenario where you cannot throws the exception, or if adding that the signature makes no sense because it reflects an implementation detail and not an inherent aspect of what the method is trying to do:
public static FileInputStream f1(String fileName) {
try {
FileInputStream fis = new FileInputStream(fileName);
System.out.println("f1: File input stream created");
return fis;
} catch (IOException e) {
throw new RuntimeException("Unhandled", e);
}
}
Naturally, this is only appropriate for situations where you really don't expect that exception to occur under normal circumstances. Otherwise, either throw that exception onwards or make your own exception type and throw that instead of RuntimeException.
If you just need a ¯\(ツ)/¯ I don't really know what this means, I just want to move on and get rid of these exceptions solution: throw new RuntimeException("Uncaught", e); is correct; e.printStackTrace(); is incorrect. Update your IDE's templates.

Your method throws a checked exception which must be handled either inside of the method, or outside. Checked exception are to indicate that a problem may occur and you need to implement something to handle this scenario. Here we are worried that the file does not exist.
You have three Choices:
Return and handle value for not existing file (no exception is thrown here). So either return null, then check in main() that inputStream is not null, or return Optional<>, which is a JDK8 way to handle such scenarios.
Example:
public static FileInputStream f1(String fileName) {
try {
FileInputStream fis = new FileInputStream(fileName);
System.out.println("f1: File input stream created");
return fis;
} catch(FileNotFoundException e) {
System.out.println("Error "+e);
return null; // in case of not existing file
}
}
Wrap your checked FileNotFoundException into a custom RuntimeException. This will solve your problem with compile error, but may cause problems in the future if you will not catch this exception somewhere.
Example:
public static FileInputStream f1(String fileName) {
try {
FileInputStream fis = new FileInputStream(fileName);
System.out.println("f1: File input stream created");
return fis;
} catch(FileNotFoundException e) {
System.out.println("Error "+e);
throw new RuntimeException(e);
}
}
Instead of try-catch add this exception to your method signature:
Example:
public static FileInputStream f1(String fileName) throws FileNotFoundException{
FileInputStream fis = new FileInputStream(fileName);
System.out.println("f1: File input stream created");
return fis;
}
But if you declare a checked exception in a method at some point you will have to catch it and handle.
Option 3 is most desired.

Related

Java: Why does an unclosed stream not throw an exception?

I wanted to write to a property file. But it silently never worked. Just from the code behavior I could not notice it. I always had to open the properties file and look if the value changed. But it never did. So actually I would expect to get an exception . The problem seemed to be that I did not close the InputStream before opening the OutputStream. But I never got to know that. It cost me 3 days because I would expect either OutputStream or store function to give me some feedback. Have a look at the code.
File file = ResourceUtils.getFile("classpath:First.properties");
FileInputStream in = new FileInputStream(file);
Properties props = new Properties();
props.load(in);
System.out.println(props.getProperty("country"));
in.close(); // This I always forgot
FileOutputStream out = new FileOutputStream(file);
props.setProperty("country", "germany");
props.store(out, null);
System.out.println(props.getProperty("country"));
out.close();
As for the actual question "why does it not throw an exception", it's because there are cases you want the Stream to remain open.
class FileWriteSample implements Closeable {
FileOutputStream writeTo;
public FileWriteSample(String filename) throws IOException {
writeTo = new FileOutputStream(filename);
// should we expect an Exception here because we don't close the Stream?
// we're planning to use it later on
}
public void write(String s) {
// write to stream
}
public void close() throws IOException {
writeTo.close();
}
}
A forgotten close() statement cannot cause an exception. From the perspective of your stream everything is okay. It just didn't wrote to its destination yet. Why should it? Even when the whole program terminates there is no guaranty that the stream closes and writes its internal buffers out.[1]
You always have to call flush() or close() actively. The underlying implementation will then perform the actual write operation.
This mistake is so common that there is an extra Java-Feature to handle it. It is called try-with-resources and prevents programmers from the evil consequences of missing close() statements.
Example:
//use try-with-resources on out
private void saveProperties(Properties properties, String path) {
try(PrintStream out = new PrintStream(new FileOutputStream(path))) {
printProperties(properties,out);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// you can pass System.out as well to print to console
private void printProperties(Properties properties, PrintStream out) {
try {
properties.store(out, null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//properties.load leaves the stream open, so you have to use try-with-resources
private Properties readProperties(String path) {
try (FileInputStream in = new FileInputStream(path)) {
Properties properties = new Properties();
properties.load(in);
return properties;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
Related posts on Java Properties:
Read properties from outside of a jar: https://stackoverflow.com/a/54766296/1485527
Sorted print of properties: https://stackoverflow.com/a/54781548/1485527
Related posts on Java Streams:
Closing Streams in Java
[1] See: Josh Bloch, Effective Java,(2nd ed.), Page 27.
Avoid finalizers.[...] It is entirely possible, even likely, that a program terminates without executing finalizers on some objects that are no longer reachable.

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

Exception supposedly never thrown even though it does at runtime

I'm trying to write a small program where I came to the following problem:
In one of my methods I have the following piece of code
try{
rootHuman = Human.load(scanner.next());
}catch(FileNotFoundException f){
//Missing Code
}
where I try to catch a FileNotFoundException. So looking at the function call from Human.load() we have this piece of code
public static Human load(String filename){
try{
Human human;
FileInputStream fileIn = new FileInputStream(filename);
ObjectInputStream in = new ObjectInputStream(fileIn);
human = (Human) in.readObject();
in.close();
fileIn.close();
return human;
}catch(IOException i){
i.printStackTrace();
return null;
}catch(ClassNotFoundException c){
c.printStackTrace();
return null;
}
also when trying to catch the FileNotFoundException here I get the same problem. My Problem is that the compiler tells me that this exception is never thrown, but when I execute the code I can obviously get a FileNotFoundException when the input from scanner.next() is a filename that doesn't exist. I'm kind of pointless here so any piece of advice is very much welcome.
Thanks in advance
Your compiler complains about this:
try{
rootHuman = Human.load(scanner.next());
}catch(FileNotFoundException f){
//Missing Code
}
In your Human.load method you catch a IOException, so a FileNotFoundException (witch is actually a sub-type of IOException) will never be thrown in method "load", this catch clausule will always handle it.
Remove the try catch block when calling Human.load():
rootHuman = Human.load(scanner.next());

Java: Does nu.xom.Builder properly close Files?

I am using nu.xom.* for my project, link found at http://www.xom.nu/. My question is about the following part of my code:
private void open() {
builder = new Builder();
try {
document = builder.build(file);
} catch (ParsingException | IOException ex) {
Logger.getLogger(InvoiceData.class.getName()).log(Level.SEVERE, null, ex);
}
}
I have some unwanted file locks in my program and am practically checking all places where I open a file. Now it struck me here that builder.build(File file) does implement Closeable, so I myself am not sure here whether it closes the file properly or not.
Can anyone shed some light on this?
Regards.
Fortunately the XOM library is open source, so you can take a look at the source code of nu.xom.Builder.build(File):
public Document build(File in)
throws ParsingException, ValidityException, IOException {
InputStream fin = new FileInputStream(in);
// [...]
String base = url.toString();
try {
Document doc = build(fin, base);
return doc;
}
finally {
fin.close();
}
}
So you pass a File instance to the build() method and inside this method a FileInputStream is opened and closed at the end.
There is a part after new FileInputStream(in) which is not enclosed by a try block. If this code throws an unchecked exception it is possible that the input stream isn't closed. But if you don't catch an exception then you can be sure, that the input stream is closed properly.

Assistance in writing my file writer method for a servlet

I have a simple servlet where I write to a file if it has a queryparameter 'hello', and since this is a test I want to display the error the the webpage also.
IntelliJ is complaining that I am not catching the IOException, not sure what's wrong:
private static void WriteToFile(String filePath, String fileName, String fileData) {
FileWriter writer = null;
try {
writer = new FileWriter(fileName);
writer.write(fileData);
} catch(IOException ex) {
} finally {
if(writer != null) {
writer.close();
}
}
}
Also, in my exception, I noticed on the web most people write:
How can I output the error to the web page?
You're not catching IOException when you call writer.close(); in the finally block.
You're also completely swallowing any IOException thrown in the main code, which is a really bad idea. If something's goes wrong, you'll have no idea what's happening.
I would personally suggest that you let that method throw the exception to the caller:
private static void writeToFile(String filePath, String fileName,
String fileData) throws IOException {
FileWriter writer = new FileWriter(fileName);
try {
writer.write(fileData);
} finally {
writer.close();
}
}
Note that if the try block throws an exception and the finally block does, you'll effectively "lose" the original exception. You may want to suppress exceptions throw when closing.
Or just use Guava which makes all of this simpler anyway with its Files class.
Or if you're using Java 7, you could use a try-with-resources statement.
(I note that you're ignoring filePath by the way - why?)
You can write in catch block too : writer.write(errorMessage);
or you may redirect to Error page if error occured

Categories