2

Fairly new to Java and I'm trying to use a fileChooser to open a file and read the information. I'm at the stage where I am trying to create a fileInputStream and inputStreamReader. When creating I was being given a FileNotFoundException despite the file existing. Not too clear why this occurs but I've placed this code into a try/catch block to resolve it. Unfortunately, I still get a cannot find symbol error during compilation for the variable "in". If anyone could give an explanation to these issues it would be greatly appreciated.

openFileBtn.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {    
        JFileChooser fileChooser = new JFileChooser(); 
        fileChooser.setCurrentDirectory(new File("."));
        fileChooser.setDialogTitle("Open your Rain Data.");
        int returnVal = fileChooser.showOpenDialog(null);   
        //Handles when a file is opened by the user. 
        if (returnVal == JFileChooser.APPROVE_OPTION) {     
            String absolutePath = fileChooser.getSelectedFile().getAbsolutePath();
            File file = new File(absolutePath);
            try {
                FileInputStream in = new FileInputStream(file); 
                InputStreamReader reader = new InputStreamReader(in); 
            } catch (FileNotFoundException ex) {
                System.out.println("Error - the file was unable to be read by the rain handler. Check permissions and the file.");
            } finally {
                System.out.println(file.canRead()); 
                System.out.println(file.exists());
                System.out.println(in.available());     
            }   
        } 
    }
});
Elarbi Mohamed Aymen
  • 1,617
  • 2
  • 14
  • 26
Alesi Rowland
  • 379
  • 2
  • 16
  • Post the full error message. – drum Jan 06 '19 at 15:27
  • 3
    You've declared `in` inside the `try` block, but you're trying to use it in the `finally` block where it's not in scope. – Jacob G. Jan 06 '19 at 15:27
  • 2
    @JacobG already pointed out that in is not accessible from within the finally block. You should also have a look at try-with-resources. That would help you with auto-closing the streams. – Stefan Freitag Jan 06 '19 at 15:30

3 Answers3

3

A variable defined within a specific scope such as try body is visible only within this scope. So outside the try body the variable is not accessible.
Actually you should declare it before :

File file = new File(absolutePath);
FileInputStream in = null;
try {
    in = new FileInputStream(file); 
    InputStreamReader reader = new InputStreamReader(in); 

} catch (FileNotFoundException ex) {
    System.out.println("Error - the file was unable to be read by the rain handler. Check permissions and the file.");

} finally {
    System.out.println(file.canRead()); 
    System.out.println(file.exists());
    System.out.println(in.available());     
}   

Note that it is a bad usage of finally.
A finally clause ensures that :

the finally block is executed after the try block and any catch block that might be executed, no matter how control leaves the try block or catch block.

Generally you use it to clear resources opened/used in the try body.
Actually file or in could be null. So this code could fail with NullPointerException at runtime.
Besides your code throws some IOException, you should also catch them and not only the FileNotFoundException in the error handling :

This kind of processing have to be executed in the try only such as :

try {
    in = new FileInputStream(file); 
    InputStreamReader reader = new InputStreamReader(in); 
    System.out.println(file.canRead()); 
    System.out.println(file.exists());
    System.out.println(in.available());     

} 
 catch (FileNotFoundException ex) {
    System.out.println("Error - the file was unable to be read by the rain handler. Check permissions and the file.");
} 
 catch (IOException ex) {
        System.out.println("Error...");
 } 

And still a better way would rely on try with resources to close automatically the stream resources :

try (FileInputStream in = new FileInputStream(file);
      InputStreamReader reader = new InputStreamReader(in)){
     // ...
}
davidxxx
  • 125,838
  • 23
  • 214
  • 215
0

The standard approach is:

FileInputStream fileInputStream = null;
try {
    fileInputStream = new FileInputStream(...);
    // do something with the inputstream
} catch (IOException e) {
    // handle an exception
} finally { //  finally blocks are guaranteed to be executed
    // close() can throw an IOException too, so we got to wrap that too
    try {
        if (fileInputStream != null) {
            fileInputStream.close();
        }        
    } catch (IOException e) {
        // handle an exception, or often we just ignore it
    }
}

so in your case :

public void actionPerformed(ActionEvent e) {
     JFileChooser fileChooser = new JFileChooser();
     fileChooser.setCurrentDirectory(new File("."));
      fileChooser.setDialogTitle("Open your Rain Data.");
      int returnVal = fileChooser.showOpenDialog(null);
      //Handles when a file is opened by the user. 
      if (returnVal == JFileChooser.APPROVE_OPTION) {
          String absolutePath = fileChooser.getSelectedFile().getAbsolutePath();
          File file = new File(absolutePath);
          FileInputStream in = null;
          try {
              in = new FileInputStream(file);
              InputStreamReader reader = new InputStreamReader(in);
          } catch (FileNotFoundException ex) {
              System.out.println("Error - the file was unable to be read by the rain handler. Check permissions and the file.");
          } finally {
              System.out.println(file.canRead());
              System.out.println(file.exists());
              try {
                  System.out.println(in.available());
              } catch (IOException ex) {
                  // handle an exception, or often we just ignore it  
              }
          }
      }
  }
Elarbi Mohamed Aymen
  • 1,617
  • 2
  • 14
  • 26
0
FileInputStream in = new FileInputStream(file); 

In the posted question, reference "in" is created in the try block so it has local scope within that block. Preferred is to declare it before the try block so as to have a bigger scope.

arunveersingh
  • 391
  • 3
  • 11