{"id":"reading-files-numbers","slug":"numbers-from-a-file","title":"Files of numbers","text":"The lines of a file are Strings, just like keyboard input. In a file of numbers, each line is turned into a number with `Integer.valueOf` (or `Double.valueOf` for decimals), and then the usual tools work: a sum, a count, the largest. This file has the millimeters of rain on each day of a week:\n\n```file rain.txt\n0\n12\n3\n0\n25\n0\n0\n```\n\n```java\nimport java.nio.file.Paths;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        int total = 0;\n        int dryDays = 0;\n        int wettest = 0;\n        try (Scanner scanner = new Scanner(Paths.get(\"rain.txt\"))) {\n            while (scanner.hasNextLine()) {\n                int rain = Integer.valueOf(scanner.nextLine());\n                total += rain;\n                if (rain == 0) {\n                    dryDays++;\n                }\n                if (rain > wettest) {\n                    wettest = rain;\n                }\n            }\n        } catch (Exception e) {\n            System.out.println(\"Error: \" + e.getMessage());\n        }\n        System.out.println(\"Total: \" + total + \" mm\");\n        System.out.println(\"Dry days: \" + dryDays);\n        System.out.println(\"Wettest day: \" + wettest + \" mm\");\n    }\n}\n```\n\n```output\nTotal: 40 mm\nDry days: 4\nWettest day: 25 mm\n```\n\nStarting `wettest` at 0 works because rain is never below zero. For values that can be negative, such as temperatures, start from the first value instead: read the numbers into a list, and start from `numbers.get(0)`.\n\n### Empty lines\n\nFiles sometimes have empty lines, for example between groups of values or at the very end. An empty line isn't a number:\n\n```file steps.txt\n5200\n\n7400\n```\n\n```java\nimport java.nio.file.Paths;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        int total = 0;\n        try (Scanner scanner = new Scanner(Paths.get(\"steps.txt\"))) {\n            while (scanner.hasNextLine()) {\n                String line = scanner.nextLine();\n                total += Integer.valueOf(line);\n            }\n            System.out.println(\"Steps: \" + total);\n        } catch (Exception e) {\n            System.out.println(\"Error: \" + e.getMessage());\n        }\n    }\n}\n```\n\n```output\nError: For input string: \"\"\n```\n\n`Integer.valueOf(\"\")` threw a `NumberFormatException`, and the `catch` block caught it, as it catches any exception in the `try` block. The reading stopped at the empty line. To skip empty lines instead, check each line before turning it into a number, and go on to the next round with `continue`:\n\n```java\nString line = scanner.nextLine();\nif (line.isEmpty()) {\n    continue;\n}\ntotal += Integer.valueOf(line);\n```\n\nWith that check, the program prints `Steps: 12600`.\n","task":"The file `calls.txt` holds the length of each phone call in minutes. Fill in the blanks, so the program prints the total and the average length. For the file shown below, it prints:\n\n```\nTotal: 57 minutes\nAverage: 14.25 minutes\n```\n","kind":"fill","seed":"import java.nio.file.Paths;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        int total = 0;\n        int calls = 0;\n        try (Scanner scanner = new Scanner(Paths.get(\"calls.txt\"))) {\n            while (scanner.hasNextLine()) {\n                String line = scanner.nextLine();\n                int minutes = Integer.[[valueOf‖parseInt]](line);\n                total += minutes;\n                calls++;\n            }\n            System.out.println(\"Total: \" + total + \" minutes\");\n            System.out.println(\"Average: \" + ((double) total / [[calls]]) + \" minutes\");\n        } catch (Exception e) {\n            System.out.println(\"Error: \" + e.getMessage());\n        }\n    }\n}\n","solution":"import java.nio.file.Paths;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        int total = 0;\n        int calls = 0;\n        try (Scanner scanner = new Scanner(Paths.get(\"calls.txt\"))) {\n            while (scanner.hasNextLine()) {\n                String line = scanner.nextLine();\n                int minutes = Integer.valueOf(line);\n                total += minutes;\n                calls++;\n            }\n            System.out.println(\"Total: \" + total + \" minutes\");\n            System.out.println(\"Average: \" + ((double) total / calls) + \" minutes\");\n        } catch (Exception e) {\n            System.out.println(\"Error: \" + e.getMessage());\n        }\n    }\n}\n","hints":["A line becomes an `int` with `Integer.valueOf(line)`.","The average is the total divided by the number of calls, `calls`."],"tests":[{"name":"Test 1","stdin":"","files":{"calls.txt":"12\n3\n30\n12\n"},"expect":"Total: 57 minutes\nAverage: 14.25 minutes","hidden":false},{"name":"Test 2","stdin":"","files":{"calls.txt":"10\n20\n"},"expect":"Total: 30 minutes\nAverage: 15.0 minutes","hidden":true},{"name":"Test 3","stdin":"","files":{"calls.txt":"7\n"},"expect":"Total: 7 minutes\nAverage: 7.0 minutes","hidden":true}],"require":[],"forbid":[],"more":[{"task":"The file `temperatures.txt` has a temperature in whole degrees on each line, and some are below zero. Print the coldest and the warmest temperature, and the difference between them. The file has at least one line. For the file shown below, the program prints:\n\n```\nColdest: -7\nWarmest: 4\nDifference: 11\n```\n","kind":"code","seed":"import java.nio.file.Paths;\nimport java.util.ArrayList;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n\n    }\n}\n","solution":"import java.nio.file.Paths;\nimport java.util.ArrayList;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<Integer> temperatures = new ArrayList<>();\n        try (Scanner scanner = new Scanner(Paths.get(\"temperatures.txt\"))) {\n            while (scanner.hasNextLine()) {\n                temperatures.add(Integer.valueOf(scanner.nextLine()));\n            }\n        } catch (Exception e) {\n            System.out.println(\"Error: \" + e.getMessage());\n        }\n\n        int coldest = temperatures.get(0);\n        int warmest = temperatures.get(0);\n        for (int temperature : temperatures) {\n            if (temperature < coldest) {\n                coldest = temperature;\n            }\n            if (temperature > warmest) {\n                warmest = temperature;\n            }\n        }\n        System.out.println(\"Coldest: \" + coldest);\n        System.out.println(\"Warmest: \" + warmest);\n        System.out.println(\"Difference: \" + (warmest - coldest));\n    }\n}\n","hints":["Starting the warmest at 0 goes wrong when every temperature is below zero. Read the numbers into a list, and start both from the first one, `temperatures.get(0)`.","The difference is `warmest - coldest`."],"tests":[{"name":"Test 1","stdin":"","files":{"temperatures.txt":"-3\n-7\n2\n4\n0\n"},"expect":"Coldest: -7\nWarmest: 4\nDifference: 11","hidden":false},{"name":"Test 2","stdin":"","files":{"temperatures.txt":"-12\n-5\n-9\n"},"expect":"Coldest: -12\nWarmest: -5\nDifference: 7","hidden":true},{"name":"Test 3","stdin":"","files":{"temperatures.txt":"3\n"},"expect":"Coldest: 3\nWarmest: 3\nDifference: 0","hidden":true},{"name":"Test 4","stdin":"","files":{"temperatures.txt":"15\n21\n18\n9\n"},"expect":"Coldest: 9\nWarmest: 21\nDifference: 12","hidden":true}],"require":[],"forbid":[]},{"task":"The file `receipts.txt` has the total of each receipt, as a decimal number such as `4.5`, one per line. Empty lines separate the days, and there may be one at the end too. Skip the empty lines, and print how many receipts there are and their total. For the file shown below, the program prints:\n\n```\nReceipts: 4\nTotal: 23.75\n```\n","kind":"code","seed":"import java.nio.file.Paths;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n\n    }\n}\n","solution":"import java.nio.file.Paths;\nimport java.util.Scanner;\n\npublic class Main {\n    public static void main(String[] args) {\n        int receipts = 0;\n        double total = 0;\n        try (Scanner scanner = new Scanner(Paths.get(\"receipts.txt\"))) {\n            while (scanner.hasNextLine()) {\n                String line = scanner.nextLine();\n                if (line.isEmpty()) {\n                    continue;\n                }\n                total += Double.valueOf(line);\n                receipts++;\n            }\n        } catch (Exception e) {\n            System.out.println(\"Error: \" + e.getMessage());\n        }\n        System.out.println(\"Receipts: \" + receipts);\n        System.out.println(\"Total: \" + total);\n    }\n}\n","hints":["The total is a `double`, and a line becomes one with `Double.valueOf(line)`.","Check `line.isEmpty()` first, and `continue` to skip the line before it's counted or converted."],"tests":[{"name":"Test 1","stdin":"","files":{"receipts.txt":"4.5\n2.25\n\n10.0\n7.0\n\n"},"expect":"Receipts: 4\nTotal: 23.75","hidden":false},{"name":"Test 2","stdin":"","files":{"receipts.txt":"1.5\n\n\n2.5\n"},"expect":"Receipts: 2\nTotal: 4.0","hidden":true},{"name":"Test 3","stdin":"","files":{"receipts.txt":"0.75\n"},"expect":"Receipts: 1\nTotal: 0.75","hidden":true},{"name":"Test 4","stdin":"","files":{"receipts.txt":"12.5\n0.5\n\n0.25\n"},"expect":"Receipts: 3\nTotal: 13.25","hidden":true}],"require":[],"forbid":[]}]}