Going through a txt file and finding sum of integers with exception - java

I have program that is suppose to ask the user what txt file, go through the txt file and find all parsable ints and average them. I have the following code below, but it's giving me a bunch of errors. What is the cause of all these errors?
The txt file is:
5
15
312
16
eight seven 44
eighty-five thousand and sixty-two 13 98
93
import java.util.Scanner;
public class Ch12Pt2 {
public static void main(String[] args) throws NumberFormatException {
Scanner input = new Scanner(System.in);
System.out.print("Enter filename: ");
String filename = input.nextLine();
Scanner file = new Scanner(filename);
if(file.nextLine().equals(""))
{
System.err.println("Could not find file:" + filename);
System.exit(1);
}
do {
try {
int total = 0;
int count = 0;
int num = file.nextInt();
total = num + total;
//Display the results
System.out.println("The number of parsable numbers: " + count);
System.out.println("Average values: " + (total / count));
}
catch (NumberFormatException ex) {
System.out.println("Cannot parse " + num + " as an integer.");
file.nextInt();
}
} while (file.hasNextInt());
// Close the files
input.close();
file.close();
}
}
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1485)
at java.util.Scanner.nextInt(Scanner.java:2117)
at java.util.Scanner.nextInt(Scanner.java:2076)
at Ch12Pt2.main(Ch12Pt2.java:21)

If you look at the JavaDoc for the constructor you used, you will that it "Constructs a new Scanner that produces values scanned from the specified string." What you want is Scanner#Scanner(File source), "...a new Scanner that produces values scanned from the specified file".
Do not use do-while, it will through a null pointer if your file does not have any integers. Use while instead. Also, do not initialize any of your variables inside the loop. This will cause them to re-initialize at ever iteration.
What is the point of file.nextInt(); in your catch block? It causes the program to skip an extra integer. Remove it. Furthermore, do not call input.close();, you do not want to close System.in.
#SuppressWarnings("resource")
Scanner input = new Scanner(System.in);
System.out.println("Enter filename: ");
File file = new File(input.nextLine());
/*
* Check file existence before constructing your scanner. This will prevent a
* FileNotFoundException. Notice, I used File#exists and the NOT operator '!'
*/
if (!file.exists()) {
System.err.println("Could not find file: " + file.getName());
System.exit(0);
}
Scanner scanner = new Scanner(file);
// Initialize variables outside of loop.
int num = 0;
int total = 0;
int count = 1;
// No do-while
while (scanner.hasNextInt()) {
try {
num = scanner.nextInt();
total += num;
// Display the results
System.out.println("The number of parsable numbers: " + count);
System.out.println("Average values: " + (total / count));
// count is pointless unless you increase it after every number.
count++;
} catch (NumberFormatException ex) {
System.out.println("Cannot parse " + num + " as an integer.");
}
}
// Close the files
scanner.close();
Finally, as Mad Programmer pointed out, "eight seven" and "eighty-five thousand and sixty-two" are not numbers, thus Scanner#nextInt will not include them. A work around is to use Scanner#nextLine and parse accordingly. Something like this: How to convert words to a number?

Your code is all most all wrong. I have reworked it now it works.
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Scanner;
public class Ch12Pt2 {
public static void main(String[] args) throws NumberFormatException, FileNotFoundException {
Scanner input = new Scanner(System.in);
System.out.print("Enter filename: ");
String filename = input.nextLine();
Scanner file = new Scanner(new FileReader(filename));
int num =0;
int count =0;
int total =0;
if(file.nextLine().equals(""))
{
System.err.println("Could not find file:" + filename);
System.exit(1);
}
while (file.hasNextInt()){
try {
num = file.nextInt();
total = num + total;
count++;
}
catch (NumberFormatException ex) {
System.out.println("Cannot parse " + num + " as an integer.");
}
}
// Close the files
input.close();
file.close();
System.out.println("The number of parsable numbers: " + count);
System.out.println("Average values: " + (total / count));
}
}

Scanner file = new Scanner(filename);
Exception in thread "main" java.util.NoSuchElementException
If you're reading data from a text file using a Scanner you need to specify a File, not a string, which is why you're getting the above error.
Use:
Scanner scanner = new Scanner(new FileReader("foo.txt"));
And then recursively go through the text file like this:
while(scanner.hasNext())
Your code:
while (file.hasNextInt());
Will not work because the hasNextInt() method will stop processing the text file when it encounters anything other than an integer.
System.out.println("Cannot parse " + num + " as an integer.");
Variable num is defined in a different scope to the body that handles the exception. An additional error will be thrown because num is not defined within the NumberFormatException body.
The txt file is: 5 15 312 16 eight seven 44 eighty-five thousand and sixty-two 13 98 93
If the items in the text file are on the same line it would be better to use the split method to get all elements and then detect whether they're numbers or not.
String line = sc.nextLine();
String elements = line.split(" ");
for (String e : elements) {
// add if int, or continue iteration
}
Otherwise, try something along the lines of:
int sum = 0;
int numElements = 0;
Scanner scanner = new Scanner(new FileReader("path-to-file"));
while (scanner.hasNext()) {
try {
int temp = Integer.parseInt(sc.nextLine());
sum += temp;
numElements += 1;
}catch(NumberFormatException e) {
continue;
}
}
System.out.println("Mean: "+ (sum/numElements));

Related

Program that computes average of numbers from a file (try/catch blocks involved)

I have a program that is supposed to allow the user to enter a file name, which, if correct, computes the average of the numbers within the file and prints it out. Likewise, if the user enters the wrong file name a certain number of times, then the program quits. In the program, the "try" block is supposed to instantiate the Scanner and set fileOk to true, while the "catch" block is supposed to prompt the user to reenter the file name, read the file, and increment fileTry. The first "if" statement is also supposed to make it so the average is calculated or an error message is written on the output file (outNumbers.dat). Here is the code I have so far:
package average;
import java.io.*;
import java.util.Scanner;
public class Try
{
static Scanner inFile;
public static void main(String[] args) throws IOException
{
int fileTry = 0;
String fileName;
Scanner inName = new Scanner(System.in);
System.out.println("Enter file name>");
fileName = inName.nextLine();
boolean fileOk;
do
{
fileOk = false;
try
{
Scanner file = new Scanner(new File(fileName));
fileOk = true;
}
catch(FileNotFoundException error)
{
System.out.println("Reenter file name>");
fileName = inFile.nextLine();
fileTry++;
}
} while (!fileOk && fileTry < 4);
PrintWriter outFile = new PrintWriter(new FileWriter("outNumbers.dat"));
if (fileName != null )
{
int numDays = 0;
double average;
double inches = 0.0;
double total = 0.0;
while (inFile.hasNextFloat())
{
inches = inFile.nextFloat();
total = total + inches;
outFile.println(inches);
numDays++;
}
if (numDays == 0)
System.out.println("Average cannot be computed " +
" for 0 days.");
else
{
average = total / numDays;
outFile.println("The average rainfall over " +
numDays + " days is " + average);
}
inFile.close();
}
else
System.out.println("Error");
outFile.close();
}
}
And here is the contents of the correct file(inNumbers.dat):
2.3
3.1
0.3
1.1
2.2
2.1
0.0
0.4
0.76
0.5
1.0
0.5
This is the output I get after running the program and entering the correct file name:
Enter file name>
inNumbers.dat
Exception in thread "main" java.lang.NullPointerException
at average.Try.main(Try.java:40)
I am a bit lost on how to fix this :/
NullPointerException is very common in java. It often means that you are trying to work with an object that was never initialized. In this case, infile is only declared and never initialized.
Scanner file = new Scanner(new File(fileName));
The file variable only exists within the try block, since that's where it was declared. You probably wanted to initialize infile instead.
infile = new Scanner(new File(fileName));

JAVA- Read integers from txt file and compute integers

I need some help with the code below.
What I'm trying to do is to write a program that reads in the file and computes the average grade and prints it out. I've tried several methods, like parsing the text file into parallel arrays, but I run into the problem of having the % character at the end of the grades. The program below is meant to add integers up too but the output is "No numbers found."
This is a clip of the text file (the whole file is 14 lines of similar input):
Arthur Albert,74%
Melissa Hay,72%
William Jones,85%
Rachel Lee,68%
Joshua Planner,75%
Jennifer Ranger,76%
This is what I have so far:
final static String filename = "filesrc.txt";
public static void main(String[] args) throws IOException {
Scanner scan = null;
File f = new File(filename);
try {
scan = new Scanner(f);
} catch (FileNotFoundException e) {
System.out.println("File not found.");
System.exit(0);
}
int total = 0;
boolean foundInts = false; //flag to see if there are any integers
while (scan.hasNextLine()) { //Note change
String currentLine = scan.nextLine();
//split into words
String words[] = currentLine.split(" ");
//For each word in the line
for(String str : words) {
try {
int num = Integer.parseInt(str);
total += num;
foundInts = true;
System.out.println("Found: " + num);
}catch(NumberFormatException nfe) { }; //word is not an integer, do nothing
}
} //end while
if(!foundInts)
System.out.println("No numbers found.");
else
System.out.println("Total: " + total);
// close the scanner
scan.close();
}
}
Any help would be much appreciated!
Here's the fixed code. Instead of splitting the input using
" "
you should have split it using
","
That way when you parse the split strings you can use the substring method and parse the number portion of the input.
For example, given the string
Arthur Albert,74%
my code will split it into Arthur ALbert and 74%.
Then I can use the substring method and parse the first two characters of 74%, which will give me 74.
I wrote the code in a way so that it can handle any number between 0 and 999, and added comments when I made additions that you didn't already have. If you still have any questions however, don't be afraid to ask.
final static String filename = "filesrc.txt";
public static void main(String[] args) throws IOException {
Scanner scan = null;
File f = new File(filename);
try {
scan = new Scanner(f);
} catch (FileNotFoundException e) {
System.out.println("File not found.");
System.exit(0);
}
int total = 0;
boolean foundInts = false; //flag to see if there are any integers
int successful = 0; // I did this to keep track of the number of times
//a grade is found so I can divide the sum by the number to get the average
while (scan.hasNextLine()) { //Note change
String currentLine = scan.nextLine();
//split into words
String words[] = currentLine.split(",");
//For each word in the line
for(String str : words) {
System.out.println(str);
try {
int num = 0;
//Checks if a grade is between 0 and 9, inclusive
if(str.charAt(1) == '%') {
num = Integer.parseInt(str.substring(0,1));
successful++;
total += num;
foundInts = true;
System.out.println("Found: " + num);
}
//Checks if a grade is between 10 and 99, inclusive
else if(str.charAt(2) == '%') {
num = Integer.parseInt(str.substring(0,2));
successful++;
total += num;
foundInts = true;
System.out.println("Found: " + num);
}
//Checks if a grade is 100 or above, inclusive(obviously not above 999)
else if(str.charAt(3) == '%') {
num = Integer.parseInt(str.substring(0,3));
successful++;
total += num;
foundInts = true;
System.out.println("Found: " + num);
}
}catch(NumberFormatException nfe) { }; //word is not an integer, do nothing
}
} //end while
if(!foundInts)
System.out.println("No numbers found.");
else
System.out.println("Total: " + total/successful);
// close the scanner
scan.close();
}
Regex: ^(?<name>[^,]+),(?<score>[^%]+)
Details:
^ Asserts position at start of a line
(?<>) Named Capture Group
[^] Match a single character not present in the list
+ Matches between one and unlimited times
Java code:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
final static String filename = "C:\\text.txt";
public static void main(String[] args) throws IOException
{
String text = new Scanner(new File(filename)).useDelimiter("\\A").next();
final Matcher matches = Pattern.compile("^(?<name>[^,]+),(?<score>[^%]+)").matcher(text);
int sum = 0;
int count = 0;
while (matches.find()) {
sum += Integer.parseInt(matches.group("score"));
count++;
}
System.out.println(String.format("Average: %s%%", sum / count));
}
Output:
Avarege: 74%
If you have a small number of lines that adhere to the format you specified, you can try this (IMO) nice functional solution:
double avg = Files.readAllLines(new File(filename).toPath())
.stream()
.map(s -> s.trim().split(",")[1]) // get the percentage
.map(s -> s.substring(0, s.length() - 1)) // strip off the '%' char at the end
.mapToInt(Integer::valueOf)
.average()
.orElseThrow(() -> new RuntimeException("Empty integer stream!"));
System.out.format("Average is %.2f", avg);
Your split method is wrong, and you didn't use any Pattern and Matcher to get the int values. Here's a working example:
private final static String filename = "marks.txt";
public static void main(String[] args) {
// Init an int to store the values.
int total = 0;
// try-for method!
try (BufferedReader reader = Files.newBufferedReader(Paths.get(filename))) {
// Read line by line until there is no line to read.
String line = null;
while ((line = reader.readLine()) != null) {
// Get the numbers only uisng regex
int getNumber = Integer.parseInt(
line.replaceAll("[^0-9]", "").trim());
// Add up the total.
total += getNumber;
}
} catch (IOException e) {
System.out.println("File not found.");
e.printStackTrace();
}
// Print the total only, you know how to do the avg.
System.out.println(total);
}
You can change your code in the following way:
Matcher m;
int total = 0;
final String PATTERN = "(?<=,)\\d+(?=%)";
int count=0;
while (scan.hasNextLine()) { //Note change
String currentLine = scan.nextLine();
//split into words
m = Pattern.compile(PATTERN).matcher(currentLine);
while(m.find())
{
int num = Integer.parseInt(m.group());
total += num;
count++;
}
}
System.out.println("Total: " + total);
if(count>0)
System.out.println("Average: " + total/count + "%");
For your input, the output is
Total: 450
Average: 75%
Explanations:
I am using the following regex (?<=,)\\d+(?=%)n to extract numbers between the , and the % characters from each line.
Regex usage: https://regex101.com/r/t4yLzG/1

Read file into array returns wrong elements

I'm attempting to take an input from the user, then if it matches one of the existing files, read the file and put the words, letters, or number into an array. The "words", and "alphabet" files seem to work fine, but the "numbers" is giving me an issue. It finds the file, reads it, puts it into an array, and gives the summation of the numbers; however, the output of the array is every other number, as opposed to all numbers, like it should be doing.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
public class fileIO
{
public static void main (String[] args) throws FileNotFoundException
{
String filename;
System.out.println("Please enter name of file (alphabet,words,numbers): ");
Scanner input = new Scanner(System.in);
filename = input.nextLine();
if(filename.equals("numbers"))
{
int sum = 0;
Scanner reader = new Scanner(new File("/home/ninjew/workspace/FileIO/src/" + filename + ".txt"));
ArrayList<Integer> arr = new ArrayList<Integer>();
while(reader.hasNext())
{
arr.add(reader.nextInt());
sum = sum + reader.nextInt();
}
System.out.println(arr);
System.out.println("The summation is: " + sum);
reader.close();
}
else if(filename.equals("words") || filename.equals("alphabet"))
{
Scanner reader = new Scanner(new File("/home/ninjew/workspace/FileIO/src/" + filename + ".txt"));
// This is for words and letters within the file. Print words and letters.
ArrayList<String> arr = new ArrayList<String>();
while(reader.hasNext())
{
String line = reader.next();
Scanner scanner = new Scanner(line);
scanner.useDelimiter(",");
while(scanner.hasNext()){
arr.add(scanner.next());
}
scanner.close();
}
System.out.println(arr);
reader.close();
}
}
}
In if(filename.equals("numbers")) you are doing two reads from your file in this block, which is why it is skipping numbers
while(reader.hasNext())
{
arr.add(reader.nextInt());
sum = sum + reader.nextInt();
}
Should be
while(reader.hasNext())
{
int val = reader.nextInt();
arr.add(val);
sum = sum + val;
}
Your numbers reader loop is adding first number to the array and the next number to the sum.
If input is 1 2 3 4 5 6, your array is [1, 3, 5] and your sum is 2 + 4 + 6 = 12.
You are reading next two integers in one go. Every time you call scanner.nextInt() it will read a next int. You need to store nextInt in a temp variable and use it in both the places.
while(reader.hasNext())
{
int next = reader.nextInt();
arr.add(next);
sum = sum + next;
}

How do I achieve the following results using the PrinterWriter class from a text file?

My application here prompts the user for a text file, mixed.txt which contains
12.2 Andrew
22 Simon
Sophie 33.33
10 Fred
21.21 Hank
Candice 12.2222
Next, the application is to PrintWrite to all text files namely result.txt and errorlog.txt. Each line from mixed.txt should begin with a number first followed by a name. However, certain lines may contain the other way round meaning to say name then followed by a number. Those which begins with a number shall be added to a sum variable and written to the result.txt file while those lines which begin with the name along with the number shall be written to the errorlog.txt file.
Therefore, on the MS-DOS console the results are as follow:
type result.txt
Total: 65.41
type errorlog.txt
Error at line 3 - Sophie 33.33
Error at line 6 - Candice 12.2222
Ok here's my problem. I only managed to get up to the stage whereby I have had all numbers added to result.txt and names to errorlog.txt files and I have no idea how to continue from there onwards. So could you guys give me some advice or help on how to achieve the results I need?
Below will be my code:
import java.util.*;
import java.io.*;
class FileReadingExercise3 {
public static void main(String[] args) throws FileNotFoundException
{
Scanner userInput = new Scanner(System.in);
Scanner fileInput = null;
String a = null;
int sum = 0;
do {
try
{
System.out.println("Please enter the name of a file or type QUIT to finish");
a = userInput.nextLine();
if (a.equals("QUIT"))
{
System.exit(0);
}
fileInput = new Scanner(new File(a));
}
catch (FileNotFoundException e)
{
System.out.println("Error " + a + " does not exist.");
}
} while (fileInput == null);
PrintWriter output = null;
PrintWriter output2 = null;
try
{
output = new PrintWriter(new File("result.txt")); //writes all double values to the file
output2 = new PrintWriter(new File("errorlog.txt")); //writes all string values to the file
}
catch (IOException g)
{
System.out.println("Error");
System.exit(0);
}
while (fileInput.hasNext())
{
if (fileInput.hasNextDouble())
{
double num = fileInput.nextDouble();
String str = Double.toString(num);
output.println(str);
} else
{
output2.println(fileInput.next());
fileInput.next();
}
}
fileInput.close();
output.close();
output2.close();
}
}
This is the screenshot of the mixed.txt file:
You can change your while loop like this:
int lineNumber = 1;
while (fileInput.hasNextLine()) {
String line = fileInput.nextLine();
String[] data = line.split(" ");
try {
sum+= Double.valueOf(data[0]);
} catch (Exception ex) {
output2.println("Error at line "+lineNumber+ " - "+line);
}
lineNumber++;
}
output.println("Total: "+sum);
Here you can go through each line of the mixed.txt and check if it starts with a double or not. If it is double you can just add it to sum or else you can add the String to errorlog.txt. Finaly you can add the sum to result.txt
you should accumulate the result and after the loop write the summation, also you can count the lines for error using normal counter variable. for example:
double mSums =0d;
int lineCount = 1;
while (fileInput.hasNext())
{
String line = fileInput.nextLine();
String part1 = line.split(" ")[0];
if ( isNumeric(part1) ) {
mSums += Double.valueOf(part1);
}
else {
output2.println("Error at line " + lineCount + " - " + line);
}
lineCount++;
}
output.println("Totals: " + mSums);
// one way to know if this string is number or not
// http://stackoverflow.com/questions/1102891/how-to-check-if-a-string-is-a-numeric-type-in-java
public static boolean isNumeric(String str)
{
try
{
double d = Double.parseDouble(str);
}
catch(NumberFormatException nfe)
{
return false;
}
return true;
}
this will give you the result you want in error files:
Error at line 3 - Sophie 33.33
Error at line 6 - Candice 12.2222

Open file and read Double data

Trying to read double data from the file that has different contents. For example if it is a double then the message should be "Double number is 23.5". and if it is not double number the message should be "Sixty three is not a double number". The file contents are
97.9
100.1
Three
Sixty three
77
12.4
3002.4
76
Cool
34.6
This is it
............
The code i wrote opens the file and scans next line But does not seem to properly work.
class ReadDouble
{
Scanner scan = new Scanner(System.in);
try
{
File textFile = new File ("doubleData.txt");
Scanner scanFile = new Scanner (textFile);
String str = scan.nextLine();
while(scanFile.hasNextLine())
{
double num = Double.parseDouble(str);
if(str == num)
{
System.out.println("Double number is" + str);
}
}//end while
}//end try
catch (NumberFormatException nfe)
{
System.out.println(str + "Is not a Double number");
}
}
}//end class
your try-catch should be inside the while loop, else it will come out in the first exception and rest of the lines will be ignored.
First, you should call String str = scan.nextLine(); within the loop otherwise you only ever read the first line. Also, your try / catch block should be wrapped around double num = Double.parseDouble(str); within the while loop otherwise you will not make another call to scan.nextLine() after you encounter your first non-double.
Finally, you shouldn't do if(str == num) as this will always be false. If Double.parseDouble(str) does not throw an exception, it contains the double found on that line.
Here is a solution that reads from standard in:
import java.util.Scanner;
public class ReadDouble {
public static void main(String[] args){
Scanner scan = new Scanner (System.in);
while(scan.hasNextLine()){
String str = scan.nextLine();
try {
num = Double.parseDouble(str);
System.out.println("Double number is " + num);
} catch (NumberFormatException nfe) {
System.out.println(str + " is not a Double number");
}
}
}
}
Another option is to use Scanner to see if the next element is a double if it is read it using nextDouble() otherwise read using nextLine().
Given your file format, I would not bother with Scanner. Just read each line, pass it to Double.valueOf(String) and catch the exception if it is not a double.

Categories