Reputation: 1
I need to put my searching of the file in my readData()
method in a loop that catches the fine not found exception then loops to prompt the user again for the file name until the correct one is entered. Once the proper file name is entered, then the return values pass to the other methods to continue the code.
I have tried putting the block of code into a do-while method but it results in a infinite loop. I need assistance with the semantics of this.
private static ArrayList<Double> readData() {
ArrayList<Double> inputValues = new ArrayList<>();
String inputFileName;
double value;
Scanner input = new Scanner(System.in);
System.out.print("Enter the name of the input file: ");
inputFileName = input.nextLine();
File file = new File(inputFileName);
do{
try {
input = new Scanner(file);
while (input.hasNextDouble()) {
value = input.nextDouble();
inputValues.add(value);
}
}
catch (FileNotFoundException e) {
System.out.println("File not found!");
System.out.println("Please enter file name again: ");
}
}
while(!file.exists());
return inputValues;
}
I am expecting this to explain "File not found!" then prompt again for the file name until the correct one is entered. However it only does the try-catch once and then attempts to return the inputValues return value. This causes the program to crash.
I have tried do while loop. But it ends up in an infinite loop
package weightedavgdataanalyzer;
import java.io.*;
import java.util.*;
public class WeightedAvgDataAnalyzer {
public static void main(String[] args) {
ArrayList<Double> inputValues = readData();
double weightedAvg = calcWeightedAvg(inputValues);
printResults(inputValues, weightedAvg);
}
private static void printResults(ArrayList<Double> inputValues, double weightedAvg) {
System.out.print("Enter output file name: ");
Scanner input = new Scanner(System.in);
String outputFile = input.nextLine();
try {
PrintWriter writer = new PrintWriter(outputFile);
writer.print("The weighted average of the numbers is " + weightedAvg + ", when using the data ");
for (int i = 2; i < inputValues.size(); i++) {
writer.print(inputValues.get(i) + ", ");
}
writer.println("where " + inputValues.get(0)
+ " is the weight used, and the average is computed after dropping the lowest "
+ Integer.valueOf((int) inputValues.get(1).doubleValue()) + " values.");
writer.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
}
private static double calcWeightedAvg(ArrayList<Double> inputValues) {
double sum = 0;
double average;
double weight = inputValues.get(0);
int toDrop = Integer.valueOf((int) inputValues.get(1).doubleValue());
ArrayList<Double> newList = new ArrayList<>();
for (int i = 2; i < inputValues.size(); i++) {
newList.add(inputValues.get(i));
}
Collections.sort(newList);
for (int i = (toDrop); i < newList.size(); i++) {
sum += weight * newList.get(i);
}
average = sum / (newList.size() - toDrop);
return average;
}
private static ArrayList<Double> readData() {
ArrayList<Double> inputValues = new ArrayList<>();
String inputFileName;
double value;
Scanner input = new Scanner(System.in);
System.out.print("Enter the name of the input file: ");
inputFileName = input.nextLine();
File file = new File(inputFileName);
do{
try {
input = new Scanner(file);
while (input.hasNextDouble()) {
value = input.nextDouble();
inputValues.add(value);
}
}
catch (FileNotFoundException e) {
System.out.println("File not found!");
System.out.println("Please enter file name again: ");
}
}
while(!file.exists());
return inputValues;
}
}
Upvotes: 0
Views: 264
Reputation: 51
You can take input and can return once file is found or else can keep recording error message
public File getFile(){
while(true) {
try (Scanner scanner = new Scanner(System.in)) {
System.out.println("Enter the name of the input file: ");
File file = new File(System.in);
if (file.exists()) {
return file;
}else{
System.out.println("File not found! Please try again ");
}
}
}
}
private List<Double> getData(File file){
List<Double> listOfDoubles = new ArrayList<>();
try(Scanner scanner = new Scanner(file)){
while(scanner.hasNextDouble()) {
listOfDoubles.add(scanner.nextDouble());
}
}
return listOfDoubles;
}
private static ArrayList<Double> readData() {
ArrayList<Double> inputValues = new ArrayList<>();
File inputFile = getFile();
return getData(inputFile);
}
Upvotes: 0
Reputation: 4667
The other answers have not addressed that it is bad practice to control the flow of your code using catch
and exception
. You should reserve using your catch block for typically printing your errors or logging them.
I moved the logic of asking for the file into a loop that does not depend on an exception
to correctly execute and placed it into a reusable method.
Here is what this change would look like:
ArrayList<Double> inputValues = new ArrayList<>();
double value;
File file = promptForFile(); //Condensed into a clean reusable single line of code
try {
Scanner input = new Scanner(file);
while (input.hasNextDouble()) {
value = input.nextDouble();
inputValues.add(value);
}
} catch (FileNotFoundException e) {
e.printStackTrace(); //Or log the error
}
And the method you can reuse anywhere for a new prompt:
public static File promptForFile()
{
System.out.print("Enter the name of the input file: ");
Scanner input = new Scanner(System.in);
String inputFileName = input.nextLine();
File file = new File(inputFileName);
while(!file.exists() && !file.isDirectory())
{
System.out.println("File not found!");
System.out.println("Please enter file name again: ");
inputFileName = input.nextLine();
file = new File(inputFileName);
}
return file;
}
Now the logic of your code is separated from searching for the file and the code is extremely reusable and readable.
This couldn't be done before since you had two different logics mixed intertwined.
Upvotes: 1
Reputation: 421
The problem is when the exception is caught, you never ask for a new file name, so you are running the code on the same faulty file path over and over again. To fix this, just move this code block:
System.out.print("Enter the name of the input file: ");
inputFileName = input.nextLine();
File file = new File(inputFileName);
inside the loop.
You may also want to eliminate a condition on your loop, and instead add a return;
at the end of your try block.
private static ArrayList<Double> readData() {
ArrayList<Double> inputValues = new ArrayList<>();
String inputFileName;
double value;
Scanner input = new Scanner(System.in);
while (true) {
try {
// Get response in the loop, instead of one time-only
System.out.print("Enter the name of the input file: ");
inputFileName = input.nextLine();
File file = new File(inputFileName);
input = new Scanner(file);
while (input.hasNextDouble()) {
value = input.nextDouble();
inputValues.add(value);
}
// Add your return statement here to get rid of the conditional
// loop.
return inputValues;
}
catch (FileNotFoundException e) {
System.out.println("File not found!");
System.out.println("Please enter file name again: ");
}
}
}
Upvotes: 0
Reputation: 693
File myFile = new File("myFile.txt");
while(!myFile.exists()){
//re-enter filename and instantiate myFile as a new object using it as the argument
}
could just check whether the file exists in a loop like so before using it. The issue with looping for the FileNotFoundException is that your writer is what throws that, so you would have to constantly instantiate the writer and check whether the exception is thrown before possibly looping again, which isn't ideal.
Upvotes: 0
Reputation: 6435
Move the initialization of File file = new File(inputFileName);
inside the loop as well as the "ask for new file name line". And last step is to also check if the file is an directory. You can't read directories with a Scanner
, but file.exists()
will still return true
private static ArrayList<Double> readData() {
ArrayList<Double> inputValues = new ArrayList<>();
String inputFileName;
double value;
Scanner input = new Scanner(System.in);
File file;
System.out.print("Enter the name of the input file: ");
do {
inputFileName = input.nextLine();
file = new File(inputFileName);
try {
input = new Scanner(file);
while (input.hasNextDouble()) {
value = input.nextDouble();
inputValues.add(value);
}
} catch (FileNotFoundException e) {
System.out.println("File not found!");
System.out.println("Please enter file name again: ");
}
} while (!file.exists() && !file.isDirectory());
return inputValues;
}
Upvotes: 3