5

I have a class PDF which implements an interface fileReader.

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class PDF implements fileReader {
    @Override
    public byte[] readFile(File pdfDoc) {
        if (!pdfDoc.exists()) {
            System.out.println("Could not find" + pdfDoc.getName() + " on the specified path");
            return null;
        }
        FileInputStream fin = null;
        try {
            fin = new FileInputStream(pdfDoc);
        } catch (FileNotFoundException e) {
            System.out.println("");
            e.printStackTrace();
        }
        byte fileContent[] = new byte[(int) pdfDoc.length()];
        try {
            fin.read(fileContent);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return fileContent;
    }
}

import java.io.File;
public interface fileReader {
    <T> T readFile(File fileObject);
}

I notice that there are scope issues for variables fin.

Another implementation I made was:

public byte[] readFile1(File pdfDoc) {
        if (!pdfDoc.exists()) {
            System.out.println("Could not find" + pdfDoc.getName() + " on the specified path");
            return null;
        }
        FileInputStream fin = null;
        try {
            fin = new FileInputStream(pdfDoc);
            byte fileContent[] = new byte[(int) pdfDoc.length()];
            try {
                fin.read(fileContent);
            } catch (IOException e) {
                System.out.println("");
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            System.out.println("");
            e.printStackTrace();
        }
        return fileContent;
    }

But now I could not access fileContent.

How can I combine the try-catches so that I don't have scope problems? Can there be a better design approach to this problem? I have to make functions for reading three different types of file.

1
  • 2
    What exactly are your scope problems? Commented Jun 23, 2015 at 18:04

6 Answers 6

5

Since Java 7 you can combine the try-catch as follows:

    FileInputStream fin = null;
    try {
        fin = new FileInputStream(pdfDoc);
        byte fileContent[] = new byte[(int) pdfDoc.length()];
        fin.read(fileContent);
    } catch (IOException | FileNotFoundException e) {
        System.out.println("");
        e.printStackTrace();
    }

Which, in my opinion, makes the code cleaner and variable scopes more obvious.

Sign up to request clarification or add additional context in comments.

4 Comments

Oh nice, I like that much better than what I suggested. I didn't know that was possible. Learning something new :)
@DrZoo: That's the beauty of Java, it keeps you on your toes ;)
I tried this but I get Alternatives in a multi-catch statement cannot be related by subclassing Alternative java.io.FileNotFoundException is a subclass of alternative java.io.IOException. I am using Java7 on Intellij
Makes sense. In that case you just need to catch IOException, since FileNotFoundException is a sub-class of IOException.
3

You can nest the try catch statements:

    try {
       FileInputStream fin = new FileInputStream(pdfDoc);
       byte fileContent[] = new byte[(int) pdfDoc.length()];
       try {
          fin.read(fileContent);
          return fileContent;
       } catch (IOException e) {
         e.printStackTrace();
       } finally {
         fin.close();
       }

    } catch (FileNotFoundException e) {
        System.out.println("");
        e.printStackTrace();
    }
    return null;

Note that I added a close() in a finally clause to clean up. And also returning null is probably not what you want in case of error, but that's application specific.

1 Comment

I get it. I had tried that that but in a wrong way. Thanks
2

You can have one try with multiple catch blocks.

try {
    //do stuff
}
catch (FileNotFoundException e) {
        System.out.println("");
        e.printStackTrace();
}
catch (IOException e) {
        e.printStackTrace();
}

Comments

2

You can modify this part:

        FileInputStream fin = null;
        try {
            fin = new FileInputStream(pdfDoc);
        } catch (FileNotFoundException e) {
            System.out.println("");
            e.printStackTrace();
        }
        byte fileContent[] = new byte[(int) pdfDoc.length()];
        try {
            fin.read(fileContent);
        } catch (IOException e) {
            e.printStackTrace();
        }

By

{
......
       FileInputStream fin = null;
       byte fileContent[]=null;
        try {
            fin = new FileInputStream(pdfDoc);
            fileContent = new byte[(int) pdfDoc.length()];
            fin.read(fileContent);
        } catch (FileNotFoundException e) {
            System.out.println("");
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        }
        return fileContent
    }

1 Comment

It depends of the Java version if you are working with java 7 or newer you can use only one catch block like this catch (IOException | FileNotFoundException e)
1

I would write like this:

public byte[] readFile(File pdfDoc) {
    if (!pdfDoc.exists()) {
        System.out.println("Could not find" + pdfDoc.getName() + " on the specified path");
        return null;
    }
    FileInputStream fin = null;
    byte fileContent[] = new byte[(int) pdfDoc.length()];

    try {
        fin = new FileInputStream(pdfDoc);
        fin.read(fileContent);
    } catch (FileNotFoundException e) {
        System.out.println("");
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (null != fin) {
            fin.close();
        }
    }   
    return fileContent;
}

Comments

0

Since Java 7, there is a nice utility methods for reading the entire content of a file:

return Files.readAllBytes(pdfFile.toPath());

This method will open and close the FileInputStream for you, so you don't need to do this yourself. It throws an IOException if something goes wrong. Usually, it's best to let this exception propagate to the caller, but if you really want to return null in that case, you can accomplish this as follows:

try {
    return Files.readAllBytes(pdfFile.toPath());
} catch (IOException e) {
    e.printStackTrace();
    return null;
}

This also has the nice advantage that the value returned in that case is explicit - or did you really mean to return an array filled with 0 values if the file could no longer be found, as your current code does?

Note that since NoSuchFileException is a subclass of IOException, the catch block will handle both. If you want to handle it differently you can write a separate catch block for the NoSuchFileException:

try {
    return Files.readAllBytes(pdfFile.toPath());
} catch (NoSuchFileException e) {
    System.err.println("Oh no, the file has disappeared.");
    e.printStackTrace();
    return null;
} catch (IOException e) {
    System.err.println("The file exists, but could not be read.");
    e.printStackTrace();
    return null;
}

Finally, I should probably mention that your file reading code is incorrect, as InputStream.read() does not necessarily read the entire file at once. That's why it returns the number of bytes read so you can invoke it again for the rest of the file. But as I said, since Java 7 you don't need to use such low level APIs (unless the file is too big to fit into memory, of course).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.