Unbreakable average program I'm creating a program that averages four numbers - three from a file and one from user input. Simple enough. But the catch is, the professor is going to be deliberately trying to break the program. 

I'd like advice in any regard, but remember the focus is on robustness. 

import java.util.*;
import java.io.*;

public class average {
    public static void main (String[] args) throws IOException{
        double[] nums = new double[4];
        nums = inputHandler();
        System.out.println("Average " + findAverage(nums));

        System.out.println("End Program.");
    }

    public static double findAverage(double[] nums){
        double average = 0.0;
        final double N = 4.0;

        for(int i = 0; i &lt; N; i++){
            average += nums[i] / N;
        }

        return average;
    }

    public static double[] inputHandler() throws IOException{
        Scanner input = new Scanner(System.in);
        double[] nums = new double[4];
        double[] fileNums = new double[3];

        // get first three numbers from file
        System.out.print("Enter the name of the file which contains the first three numbers: ");
        fileNums = fileInput(input.nextLine());
        System.out.println();

        // copy numbers from fileNums[] to nums[]
        for(int i = 0; i &lt; 3; i++){
            nums[i] = fileNums[i];
        }

        //get last number from user input
        System.out.print("Enter the fourth number: ");
        nums[3] = userInput(input.nextLine());
        System.out.println();

        input.close();

        return nums;
    }

    public static double[] fileInput(String fileName) throws IOException{
        double[] nums = new double[3];

        System.out.println();

        File file = new File(fileName);

        if(!file.isFile()){
            System.err.println("ERROR: File does not exist.");
            System.exit(-1);
        }

        System.out.println(fileName + ":");

        Scanner input = new Scanner(file);
        String cur = "";

        for(int i = 0; i &lt; 3; i++){

            if(!input.hasNext()){
                System.err.println("ERROR: File does not contain enough numbers.");
                System.exit(-1);
            }

            cur = input.next();

            System.out.println("Number " + (i + 1) + ": " + cur);

            if(cur.matches("-?\\d+(\\.\\d+)?")){ //regex ensures numeric input
                if(Double.parseDouble(cur) &lt; 1.7e308){
                    nums[i] = Double.parseDouble(cur);
                }
                else{
                    System.err.println("ERROR: Number too large");
                    System.exit(-1);
                }
            }
            else{
                System.err.println("ERROR: Non numeric input. Please check your file and try again.");
                System.exit(-1);
            }
        }

        input.close();

        return nums;
    }

    public static double userInput(String userInput){
        double num = 0;

        if(userInput.matches("-?\\d+(\\.\\d+)?")){ //regex ensures input is numeric
            num = Double.parseDouble(userInput);
        }
        else{
            System.err.println("ERROR: Non numeric input. Please check your file and try again.");
            System.exit(-1);
        }

        return num;
    }
}
First, use try/catch blocks around parts that can throw exceptions.  For example, what happens when an IOException is thrown by the file, perhaps because the data is corrupted and the file exists, but cannot be opened?

Second, I don't know what constitutes failure, but an app-closing failure is failure in my book:

if(!file.isFile()){
    System.err.println("ERROR: File does not exist.");
    System.exit(-1);
}


Third, @SirPython is right - use the built-in method for reading your number.  There are built-in functions provided for reading both doubles and ints, whichever your program needs.

Fourth, this will not necessarily help robustness, split your method logic up.  You are doing a lot of printing in your fileInput() method.  Do your printing in a dedicated method.  Do your input in a dedicated method.  Feel free to throw an exception when exceptional behavior happens, but be sure to handle the exception.  Split your logic up into bite-sized components and implement them separately - this will make reuse easy.

Fifth, recover from your errors.  If you need, start the entire input processes over, but do not close the program.  Closing the program because of an error will probably be counted as an error, and is unacceptable in many programs.