0

I keep running into this error when compiling this code here:

TryTryAgain.java:52: error: cannot find symbol if (file.hasNextInt()) { ^ symbol: variable file location: class TryTryAgain

It's not picking up the file symbol I defined in the try-catch block within that do-while loop while compiling. I'm not really sure how to fix this as it has to be in there or else I wouldn't be able to throw the exception and repeat until a valid file name is given.

import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.NoSuchElementException;
import java.io.IOException;
import java.util.InputMismatchException;

public class TryTryAgain {

  public static void main(String[] args) {
  
    Scanner userInp = new Scanner(System.in);
    
    System.out.print("Please enter the name of the file: ");
    String userFile = userInp.next();
    
    boolean fileAccepted = false;
    
    do {
      try {
        Scanner file = new Scanner(new File(userFile));
        fileAccepted = true;
      } catch (FileNotFoundException e) {
        System.out.println(userFile + " (The system cannot find the file specified)");
        System.out.print("Please enter a valid file name: ");
        userFile = userInp.next();
      }
    } while (fileAccepted == false);
    
    int currentHighest = 0;
    int currentLowest = 2147483647;
    int totalOf = 0;
    double totalNums = 0.0;
    int currentNum;
    
    //Making these to make the output look like the example ones
    String total = "Total";
    String min = "Min";
    String max = "Max";
    String average = "Average";
    
    do {

      if (file.hasNextInt()) {
        totalNums++;
        currentNum = file.nextInt();
        totalOf += currentNum;
        if (currentHighest < currentNum) {
          currentHighest = currentNum;
        }
        if (currentLowest > currentNum) {
          currentLowest = currentNum;
        }
      } else if (file.hasNextLine()) {
        System.out.println("Skipping over invalid input: " + file.nextLine());
      } else if (file.hasNextDouble()) {
        System.out.println("Skipping over invalid input: " + file.nextDouble());      
      }
      
    } while (file.hasNextInt() || file.hasNextLine() || file.hasNextDouble());
    
    file.close();
    
    if (totalNums > 0) {
      double averageVal = (totalOf / totalNums);
      System.out.printf("%7s: %d", total, totalOf);
      System.out.printf("%7s: %d", min, currentLowest);
      System.out.printf("%7s: %d", max, currentHighest);
      System.out.printf("%7s: %d", average, averageVal);
    } else {
      System.out.println("No valid data found. No stats available.");
    }
 
  } //end main
}

2 Answers2

1

I would suggest using a try-with-resources statement and moving the processing logic and perhaps the display logic to their own separate methods. The try-with-resources means you don't need to explicitly call file.close() and you cannot forget, nor can it be missed if some RuntimeException occurs in your code due to a null pointer, input mismatch, or any other unexpected problem. Some people would frown on the while (true) here and exiting the loop with break; but I think it's cleaner than using the separate condition variable and is all right as long as the loop body is kept simple, which it is if you extract the processing and display logic to their own methods. But if you prefer the condition variable on the loop, that is of course always an option.

public static void main(String[] args) {
  Scanner userInp = new Scanner(System.in);
  
  System.out.print("Please enter the name of the file: ");
  String userFile = userInp.next();
  
  while (true) {
    try (Scanner file = new Scanner(new File(userFile))) {
      process(file);
      break;
    } catch (FileNotFoundException e) {
      System.out.println(userFile + " (The system cannot find the file specified)");
      System.out.print("Please enter a valid file name: ");
      userFile = userInp.next();
    }
  }
}

public static void process(Scanner file) {
  int currentHighest = 0;
  int currentLowest = 2147483647;
  int totalOf = 0;
  double totalNums = 0.0;
  int currentNum;
  
  do {
    if (file.hasNextInt()) {
      totalNums++;
      currentNum = file.nextInt();
      totalOf += currentNum;
      if (currentHighest < currentNum) {
        currentHighest = currentNum;
      }
      if (currentLowest > currentNum) {
        currentLowest = currentNum;
      }
    } else if (file.hasNextLine()) {
      System.out.println("Skipping over invalid input: " + file.nextLine());
    } else if (file.hasNextDouble()) {
      System.out.println("Skipping over invalid input: " + file.nextDouble());      
    }
  } while (file.hasNextInt() || file.hasNextLine() || file.hasNextDouble());

  display(totalNums, totalOf, currentLowest, currentHighest);
}

public static void display(int totalNums, int totalOf, int lowest, int highest) {
  String total = "Total";
  String min = "Min";
  String max = "Max";
  String average = "Average";
  
  if (totalNums > 0) {
    double averageVal = (totalOf / totalNums);
    System.out.printf("%7s: %d", total, totalOf);
    System.out.printf("%7s: %d", min, lowest);
    System.out.printf("%7s: %d", max, highest);
    System.out.printf("%7s: %d", average, averageVal);
  } else {
    System.out.println("No valid data found. No stats available.");
  }
}
David Conrad
  • 15,432
  • 2
  • 42
  • 54
0

You are referring to file that doesn't exist in the context of the do-while loop. You create and establish the file inside a try catch at the beginning of your class. Move the logic for opening/closing the file into a single try catch, and the try section should contain the logic for reading the file.

try 
{
    // logic for opening file
    // log for reading (the do/while that processes the file)
}catch(FileNotFound){
CBredlow
  • 2,790
  • 2
  • 28
  • 47
  • 1
    And then make it a try-with-resources statement, so you don't have to explicitly close the file, and can't forget (or miss closing it because an exception took you out of the method before you got to close it), and move the processing logic into a separate method that takes the file scanner as a parameter. – David Conrad Mar 04 '22 at 19:59
  • 1
    @DavidConrad I completely forgot about that, that would be a lot better too. – CBredlow Mar 04 '22 at 20:01