While loop trouble for a file reader? - java

I am creating a program for class that reads in a CSV file and does various mathematical equations on the data given in the file.
The CSV file is in the set up:
longitude1, latitude1, timeStamp1
longitude2, latitude2, timeStamp2
longitude3, latitude3, timeStamp3
(and it continues on for approximately 100 different coordinates).
Right now I am focusing on the longitude values---I am having difficulty getting my while loop to perform the operations i need it too. I need to be able to get the program to subtract longitude2 from longitude1 (where lon1 and lon2 are changing to as we go through the loop...ultimately going through every coordinate).
The problem I am having is that the loop isn't creating an 'overlap' (for lack of better term). It's performing the math on the first two coordinates and then skipping down to the next two... thus skipping every other operation.
[ i.e. : the loop performing: lon2--lon1 and lon4-lon3 but is skipping lon3-lon2 ]
I have a hunch that my problem lies at the start of my while loop but I honestly don't know how to fix it. I would love some help.
Below is the code I have currently:
import java.io.*;
import java.util.*;
public class SearchAndR {
public static void main(String[] args) throws FileNotFoundException {
// creates a Scanner called "keyboard" to read in the file name
Scanner keyboard = new Scanner(System.in);
// prompts user for file name
System.out.println("Enter the name of the file you intend to read in");
// Stores file name as a string so that we may read it in
String file = keyboard.nextLine();
// creates a new Scanner called fr(short for filereader) so we can read
// in the file
// then we create a File object using the constructor new with the class
// "File"
// this takes in our string "file" as a parameter to read it in
// reading in our file object to the scanner
Scanner fr = new Scanner(new File(file));
// Creating format for hike1.csv file
System.out.println("--- Hike Analysis ---");
System.out.println("File: " + file);
// Calling HW4 Class to use in the rest of the program
HW4Util util = new HW4Util();
// Establishing counting variable for distance for the while loop
double totaldistance = 0;
while (fr.hasNextLine()) {
String line = fr.nextLine();
String[] stamp1 = line.split(",");
String line2 = fr.nextLine();
String[] stamp2 = line2.split(",");
double lon1 = Double.parseDouble(stamp1[0]);
double lat1 = Double.parseDouble(stamp1[1]);
String time1 = (stamp1[2]);
double lon2 = Double.parseDouble(stamp2[0]);
double lat2 = Double.parseDouble(stamp2[1]);
String time2 = (stamp2[2]);
// This is just to check to see if the overlap is occurring!
// This should not be included in the project.
System.out.println("this is longitude" +lon1);
System.out.println("this is longitude" +lon2);
// returns the distance between two coordinates as a fraction of a
// mile
double dist = util.distance(lat1, lon1, lat2, lon2);
totaldistance = totaldistance + dist;
totaldistance = (double) (Math.round(totaldistance * 10000)) / 10000;
}
System.out.println("Total distance traveled: " + totaldistance + " miles");
} // end method main
} // end class filereader

Its because you're reading 2 lines in one loop run. I'd suggest do something like this:
String previousLine;
String[] previousStamp;
if (fr.hasNextLine())
{
previousLine = fr.nextLine();
previousStamp = previousLine.split(",");
}
while (fr.hasNextLine()) {
String currentLine = fr.nextLine();
String[] currentStamp = line.split(",");
//do your math here
//...
//swap values
previousStamp = currentStamp;
}
Why its not working as you intended? Well, imagine a pointer thats currently at the beggining of your file.
With fr.nextLine() you are reading line its currently pointed and the pointer goes down.
In one run of your loop you read 2 consecutive lines, do your math and in next run again reading 2 more lines

Related

Having problems scanning a String from a file in Java

I'm trying to scan a line of text from a .txt file, split it up into seven numbers, change two of the numbers, and then write the new numbers back into the .txt file. The code below works fine the first time, but seems to have issues with reading from the text file a second time for the new starting String. I've done very similar things multiple times and had no issues, so I'm really not sure why I'm having problems this time around. The code I currently have is:
public void addWin(int numGuesses) throws IOException {
FileWriter writer = new FileWriter(*filepath*);
Scanner scan = new Scanner(new File(*filepath*));
String temp = "0;0;0;0;0;0;0;";
if (scan.hasNextLine()) {
temp = scan.nextLine();
}
String[] statsArr = temp.split(";");
scan.close();
statsArr[0] = Integer.toString(Integer.parseInt(statsArr[0]) + 1);
statsArr[numGuesses] = Integer.toString(Integer.parseInt(statsArr[numGuesses]) + 1);
for (int i = 0; i < statsArr.length; i++) {
writer.append(statsArr[i] + ";");
}
writer.close();
}
Some extra context if needed, this is essentially for a Wordle clone sort of thing for a Discord bot I have. numGuesses is the number of guesses it took to get the word correct. The String being written in and being read is 7 numbers divided up by a semicolon, the first number is the current win streak, the second number is number of times you've won in 1 guess, and so on. The testing I've done seems to place the error somewhere before the scanner closes. A first run through will correctly write the numbers, so if the word was guessed in 3 attempts the file will contain "1;0;0;1;0;0;0;", but the next time the method is called it essentially starts from scratch. Checking the temp variable just after the if statement on a second run through just shows "0;0;0;0;0;0;0;". Sorry for the long-windedness, just trying to provide all possibly helpful details. Thank you in advance!
-
Consider the JavaDoc which states "Whether or not a file is available or may be created depends upon the underlying platform.". So what is happening here, is that when you use new FileWriter(*filepath*) the file is being locked/created blank, so when you use new Scanner(new File(*filepath*)); and scan.hasNextLine() you get a null/empty value.
The easy solution is to simply move the FileWriter further down in your code, and only open it after the scanner has been closed. Also add an else to your if statement so you know if there is an issue with reading from the scanner:
//Move the below line to be later in the code
//FileWriter writer = new FileWriter(*filepath*);
Scanner scan = new Scanner(new File(*filepath*));
String temp = "0;0;0;0;0;0;0;";
if (scan.hasNextLine()) {
temp = scan.nextLine();
}
//Add some debugging
else{
System.out.println("ERROR no data could be read");
}
String[] statsArr = temp.split(";");
scan.close();
statsArr[0] = Integer.toString(Integer.parseInt(statsArr[0]) + 1);
statsArr[numGuesses] = Integer.toString(Integer.parseInt(statsArr[numGuesses]) + 1);
//Create the flie writer here instead
FileWriter writer = new FileWriter(*filepath*);
for (int i = 0; i < statsArr.length; i++) {
writer.append(statsArr[i] + ";");
}
writer.close();
Now assuming the file exists and can be edited, and where numGuesses = 3, then for the following contents:
1;2;3;4;5;6;7;
The output of running the code is as expected (+1 to the 0 and 3rd index)
2;2;3;5;5;6;7;
The reason you only saw 0;0;0;0;0;0;0; was because the code was failing to read from the scanner, and always using the temp value from this line String temp = "0;0;0;0;0;0;0;";. By adding the else check above we can see when it fails.
FileWriter writer = new FileWriter(*filepath*); clears the contents of the file you are trying to read from. You need to move this line after scan.close();

"java.lang.NumberFormatException: empty String" with a not empty String

I am currently working on a personal project outside of class and am running into some issues while reading in a text file into a linked list. When reading in the first double I get a
java.lang.NumberFormatException: empty String
error. I added a print line into the program to print out what I am trying to parse into a double and the variable is in fact, not empty, and is in fact a double.
Like I said above, I added a print line to print out the string I am trying to parse into a double and it seems to be okay. Here is the String that is read in and split into the array I am printing from:
500.0 % 04/05/2019 % This is paycheck 1 % true % 49.5
I have to parse two strings into doubles and I only run into problems with the first one. When I comment out the first double being parsed, the program runs with no problems. Here is the full output from running to program
*File loading*
*500.0*
*Exception in thread "main" java.lang.NumberFormatException: empty String*
*at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)*
*at sun.misc.FloatingDecimal.parseDouble(Unknown Source)*
*at java.lang.Double.parseDouble(Unknown Source)*
*at fileHandling.readPaycheck(fileHandling.java:194)*
*at UserMenu.main(UserMenu.java:20)*
The problems happens in the "Splitting the array into its appropriate temp variables" section in this line of code:
payCheckAmount = Double.parseDouble(tempArray[0]);
Here is the code for the method this is in
public void readPaycheck(LinkedList<PayCheck> paycheck) throws IOException {
// Declare Variables
Scanner sc = new Scanner(payChecks); // Scanner used to read in from the payChecks text file
String temp; // A string used to hold the data read in from the file temporarily
String[] tempArray; // A String array used to temporarily hold data from the text file
double payCheckAmount; // A double holding the amount of the paycheck
String paycheckDate; // A string holding the date of the paycheck
String description; // A string holding a description of the paycheck
boolean payCheckSplit; // A boolean stating if the paycheck has been split or not
double amountUnSplit; // A double
// A while loop that runs while the text file still has data in it
while (sc.hasNextLine()) {
// Reading in a new line from the paycheck file
temp = sc.nextLine();
// Splitting the line into an array
tempArray = temp.split(" % ");
// Temp output used for testing of the issue at hand
System.out.println(tempArray[0]);
// Splitting the array into its appropriate temp variables
payCheckAmount = Double.parseDouble(tempArray[0]);
paycheckDate = tempArray[1];
description = tempArray[2];
payCheckSplit = Boolean.parseBoolean(tempArray[3]);
amountUnSplit = Double.parseDouble(tempArray[4]);
// putting the temp variables into a temp paycheck object
PayCheck tempCheck = new PayCheck(payCheckAmount, paycheckDate, description, payCheckSplit, amountUnSplit);
paycheck.add(tempCheck);
}
}
Edit:
Here is a Minimal, Complete, and Verifiable example of the problem I am running into:
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class test {
public static void main(String[] args) throws IOException {
// Declare Variables
File payChecks = new File("C:\\Users\\zwtw\\Documents\\paychecks.txt");
Scanner sc = new Scanner(payChecks);
while (sc.hasNextLine()) {
String temp = sc.nextLine();
String[] tempArray = temp.split(" % ");
System.out.println(tempArray[0]);
// Splitting the array into its appropriate temp variables
double payCheckAmount = Double.parseDouble(tempArray[0]);
String paycheckDate = tempArray[1];
String description = tempArray[2];
boolean payCheckSplit = Boolean.parseBoolean(tempArray[3]);
double amountUnSplit = Double.parseDouble(tempArray[4]);
}
}
}
Here is the content of the text file mentioned in the code above:
500.0 % 04/05/2019 % This is paycheck 1 % true % 49.5
450.0 % 04/09/2019 % This is paycheck 2 % true % 49.75
Your text file likely contains empty lines. You can either remove the new lines in the text file, change how the text file is created, or just skip the empty lines when you read it.
This is how you skip the empty lines:
while (sc.hasNextLine()) {
String temp = sc.nextLine();
if (temp.equals("")) { continue; } // <--- notice this line
String[] tempArray = temp.split(" % ");
System.out.println(tempArray[0]);
// Splitting the array into its appropriate temp variables
double payCheckAmount = Double.parseDouble(tempArray[0]);
String paycheckDate = tempArray[1];
String description = tempArray[2];
boolean payCheckSplit = Boolean.parseBoolean(tempArray[3]);
double amountUnSplit = Double.parseDouble(tempArray[4]);
}
}

Convert string to doubles in a .txt file?

I have a .txt file of numbers that are formatted like the following:
1.2 2.3 3.4 4.5
2.0 3.0 4.0 5.0
6.0 7.0 8.0 9.0
I'm trying to use a scanner to take each line as a string, convert each number to a double and then add them together to print to a new .txt file.
My error message looks like this:
Exception in thread "main" java.lang.NumberFormatException: For input
string: "1.2 2.3 3.4 4.5" at
sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2043)
at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110) at
java.lang.Double.parseDouble(Double.java:538) at
scanstrings.ScanStrings.parseDouble(ScanStrings.java:51) at
scanstrings.ScanStrings.main(ScanStrings.java:33)
I was trying to use a split to separate each number so that they could be converted to doubles, but no matter what I do nothing seems to work, and I've found ways to split using spaces and periods but each way I try returns the same error message.
My code basically looks like this right now (I'm just starting so I'm sorry if it's just bad, I've also been messing with this for a while so some parts might just not make sense
//Construct Scanner object for the input file
Scanner input = new Scanner (new File("one.txt"));
//Construct Scanner object for the output file
PrintWriter output = new PrintWriter("result.txt");
//Read lines from the input file
while(input.hasNextLine()){
String line = input.nextLine();
String[] conv = line.split("\\s+");
String dub1 = conv[0];
String dub2 = conv[1];
String dub3 = conv[2];
String dub4 = conv[3];
//convert to double
double dub = parseDouble(line);
//compute sum
double total = 0;
if (dub != 0) //protect against division by zero
{
total += dub;
}
System.out.printf("\n", dub, total);
}
input.close();
output.close();
}
public static double parseDouble(String conv) throws NumberFormatException{
int i = 0;
while (!Character.isDigit(conv.charAt(i))) { i++; }
return Double.parseDouble(conv.substring(i).trim());
}
Welcome to StackOverflow!
You've split your line into individual terms, but then are passing the whole line to your parsing with this:
double dub = parseDouble(line);
Instead, try:
double dub = parseDouble(conv[0]);
for the first value. (You may even want to try creating a loop, for all values.)
(as far as i understood you wish to add the numbers in each line from input file, and print it on new line, in output file). An easier way would be to rely on Double.parseDouble(String) to convert the string to Double. New version of your parseDouble(line)
public static double parseDouble(String line){
double res = 0;
for(String number : line.split("\\s+") ){
try{
res += Double.parseDouble(number);
}
catch(NumberFormatException ex){
System.out.println("Cannot convert " + number + " to double");
}
finally{
return res;
}
}
So in that case, you should rename your parseDouble(String line) to getSum(String line)

Cannot print to text file from within while-loop

So I'm at a point in my program where I want to read from a csv file (which has two columns), do some light calculation on the first column (after I check whether or not it has any content), then print the new number (which I calculated from column 1 in the first file) and the contents of the second column from the original file to a new text file.
Without a while loop I have no trouble running calculations on the numbers from the original text file, then printing them to the new file. However ANY printing from inside the while loop is giving me an error. In fact, anything other than reading the file and parsing it into an array of strings is giving me an error from inside the while loop.
These are the top two lines of my stackTrace with the code I currently have posted below:
"Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 0
at finalProyect.User.makeMealPlan(User.java:476)"
Line 476 being the line in my while loop: "if (array2[0].isEmpty())"
After hours of searching and tinkering I thought it was time to ask for help. Thanks in advance for any help you can provide.
public void makeMealPlan() {
String fileIn = "mealPlan1.csv";
Scanner inputStream = null;
String fileOut = userName + ".txt";
PrintWriter outputStream = null;
try {
inputStream = new Scanner(new File(fileIn));//opens and reads pre-configured meal plan
outputStream = new PrintWriter(fileOut);//creates output file for meal plan
} catch(FileNotFoundException e3) {
fileNotFound();
e3.printStackTrace();
}
outputStream.println(toString());
outputStream.println();
String line0 = inputStream.nextLine();
String[] array0 = line0.split(","); //Splits line into an array of strings
int baseCalories = Integer.parseInt(array0[0]); //converts first item in array to integer
double caloricMultiplier = (caloricNeeds / baseCalories); //calculates the caloricMultiplier of the user
String line1 = inputStream.nextLine();//reads the next line
String[] array1 = line1.split(",");//splits the next line into array of strings
outputStream.printf("%12s %24s", array1[0], array1[1]); //prints the read line as column headers into text file
while(inputStream.hasNextLine()) {
String line = inputStream.nextLine(); //reads next line
String[] array2 = line.split(",");
if(array2[0].isEmpty()) {
outputStream.printf("%12s %24s", array2[0], array2[1]);
} else {
double quantity = Double.parseDouble(array2[0]);
quantity = (quantity * caloricMultiplier);
outputStream.printf("%12s %24s", quantity, array2[1]);
}
}
outputStream.close();
System.out.println(toString());
}
Okay, so there were a few things wrong. However with #NonSecwitter's suggestion I was able to pin it down. So first thing (again as NonSecwitter mentioned) I had empty fields in my .csv which was throwing the ArrayIndexOutOfBounds" error. So what I did was I filled every empty field in my .csv with the string "empty". Once I did that I was able to at least print the next line.
After that, I ran into another error which was that this line:
double quantity = Double.parseDouble(array2[0]);
could not be separated from the the preceding read/split statements by being inside of an if-loop. So I ended up rewriting the guts of the entire while-loop and needed to throw an exception like so:
while (inputStream.hasNextLine())
{
String[] array2 = null;
try
{
String line = inputStream.nextLine(); //reads next line
array2 = line.split(",");
double quantity = Double.parseDouble(array2[0]);
if (!isStringNumeric(array2[0]))
throw new NumberFormatException();
quantity = Math.ceil(quantity * caloricMultiplier);
outputStream.printf("%12.1f %15s\n", quantity, array2[1]);
}
catch(NumberFormatException e1)
{
if (array2[1].equals("empty"))
outputStream.printf("%12s %15s\n", " ", " ");
else
outputStream.printf("%12s %15s\n", " ", array2[1]);
}
}
While my program is now currently working just fine, I'd still really appreciate an explanation as to why I ended up having to throw an exception to get the code to work. Are there certain restrictions with using PrintWriter inside of a while-loop? Also, I very much appreciate everybody's feedback. I think with all the comments/suggestions combined I was able to determine where my problems were (just not WHY they were problems).
Thanks!!!
It would help if you provided sample CSV data and an example of the related output you expect in <userName>.txt.
Short of this I can only help insofar as saying I do not get an exception with your code.
Here is what I got with a quick Java project in Eclipse using project and class-file names gleaned from your exception output (finalProyect and User.java respectively), pasting your code into the class file (User.java), and massaging it a bit for a sanity check...
package finalProyect;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.Scanner;
public class User {
public void makeMealPlan()
{
String fileIn = "C:\\Temp\\mealPlan1.csv";//"mealPlan1.csv"; // FORNOW: adjusted to debug
Scanner inputStream = null;
String userName = "J0e3gan"; // FORNOW: added to debug
String fileOut = "C:\\Temp\\" + userName + ".txt"; // FORNOW: adjusted to debug
PrintWriter outputStream = null;
try
{
inputStream = new Scanner(new File(fileIn));//opens and reads pre-configured meal plan
outputStream = new PrintWriter(fileOut);//creates output file for meal plan
}
catch(FileNotFoundException e3)
{
//fileNotFound(); // FORNOW: commented out to debug
e3.printStackTrace();
}
outputStream.println(toString());
outputStream.println();
String line0 = inputStream.nextLine();
String[] array0 = line0.split(","); //Splits line into an array of strings
int baseCalories = Integer.parseInt(array0[0]); //converts first item in array to integer
int caloricNeeds = 2000; // added to debug
double caloricMultiplier = (caloricNeeds / baseCalories); //calculates the caloricMultiplier of the user
String line1 = inputStream.nextLine();//reads the next line
String[] array1 = line1.split(",");//splits the next line into array of strings
outputStream.printf("%12s %24s", array1[0], array1[1]); //prints the read line as column headers into text file
while (inputStream.hasNextLine())
{
String line = inputStream.nextLine(); //reads next line
String[] array2 = line.split(",");
if (array2[0].isEmpty())
outputStream.printf("%12s %24s", array2[0], array2[1]);
else
{
double quantity = Double.parseDouble(array2[0]);
quantity = (quantity * caloricMultiplier);
outputStream.printf("%12s %24s", quantity, array2[1]);
}
}
outputStream.close();
System.out.println(toString());
}
public static void main(String[] args) {
// FORNOW: to debug
User u = new User();
u.makeMealPlan();
}
}
...and an example of what it output to J0e3gan.txt...
finalProyect.User#68a6a21a
3000 40 2500.0 50 4000.0 25
...with the following (complete-WAG) data in mealPlan1.csv:
2000,20
3000,40
2500,50
4000,25
Comment out the offending code and try to println() array2[0] and see if it gives you anything.
while (inputStream.hasNextLine())
{
String line = inputStream.nextLine(); //reads next line
String[] array2 = line.split(",");
System.out.println(array2[0]);
//if (array2[0].isEmpty())
// outputStream.printf("%12s %24s", array2[0], array2[1]);
//
//else
//{
//
// double quantity = Double.parseDouble(array2[0]);
// quantity = (quantity * caloricMultiplier);
// outputStream.printf("%12s %24s", quantity, array2[1]);
//}
}
or, try to print the length. If the array were empty for some reason array2[0] would be out of bounds
System.out.println(array2.length);
I would also print line to see what it's picking up
System.out.println(line);

File I/O Basics

I'm working on a school programming lab and I've gotten stuck. The book is not too helpful in teaching how to format I/O properly, or at least I'm not understanding it properly. I need a bit of help getting on with the next steps, but here's the full requirements of the program I'm supposed to be making:
A hotel salesperson enters sales in a text file. Each line contains
the following, separated by semicolons: The name of the client, the
service sold (such as Dinner, Conference, Lodging, and so on), the
amount of the sale, and the date of that event. Write a program that
reads such a file and displays the total amount for each service
category. Display an error if the file does not exist or the format is
incorrect. In addition to the program specifications listed, your
program should both print the results as well assend the results to a
separate output file.
Example of input.txt:
Elmer Fudd;Lodging;92.00;11-01-2014
Elmer Fudd;Conference;250.00;11-02-2014
Daffy Duck;Dinner;19.89;11-02-2014
Daffy Duck;Conference;275.00;11-02-2014
Mickey Mouse;Dinner;22.50;11-02-2014
Mickey Mouse;Conference;275.00;11-02-2014
I'm currently stuck on figuring out how to get the file properly loaded and formatted, which I think I did right, but then my professor suggested breaking each into it's own line, but nowhere in my book does it clearly tell how to do that. Just to be clear, I'm not looking for a coding miracle, I just would like someone to help guide me in the right direction as to what I should do next. Possibly a better way to handle this situation in a nicely detailed guide? Nothing fancy though. Thank you in advance, and here's my current code.
import java.util.*;
import java.io.*;
public class Sales
{
public static void main(String[] args) throws FileNotFoundException
{
File inputFile = new File("input.txt");
Scanner in = new Scanner(inputFile);
PrintWriter out = new PrintWriter("output.txt");
double dinnerTotal = 0;
double conferenceTotal = 0;
double lodgingTotal = 0;
Scanner lineScanner = new Scanner(inputFile);
lineScanner.useDelimiter(";");
while (lineScanner.hasNext())
{
String line = in.nextLine(); //Here's where I'm really stuck
System.out.print(line); //Not to say I'm not stumped all over.
}
in.close();
out.close();
lineScanner.close();
}
}
From what Jason said, I'm at this now:
import java.util.*;
import java.io.*;
public class Sales
{
public static void main(String[] args) throws FileNotFoundException
{
File inputFile = new File("input.txt");
Scanner in = new Scanner(inputFile);
PrintWriter out = new PrintWriter("output.txt");
double dinnerTotal = 0;
double conferenceTotal = 0;
double lodgingTotal = 0;
while (in.hasNext())
{
String line = in.nextLine();
String[] parts = line.split(";");
if(parts[1].equals("Conference")) {
conferenceTotal += Double.parseDouble(parts[2]);
} else if(parts[1].equals("Dinner")) {
dinnerTotal += Double.parseDouble(parts[2]);
} else if(parts[1].equals("Lodging")) {
lodgingTotal += Double.parseDouble(parts[2]);
}
}
in.close();
out.close();
}
}
Stick to one scanner.
Read each line in total, rather than breaking on the ';'.
Then use String.split() to break the line of text apart at the ';' separator.
Then check the second part (zero based index) to retrieve the service category and add the value in the third part to the relevant total.
String line = in.nextLine();
String[] parts = line.split(";");
if(parts[1].equals("Conference")) {
conferenceTotal += Double.parseDouble(parts[2]);
} else if(parts[1].equals("Dinner")) {
dinnerTotal += Double.parseDouble(parts[2]);
} else if(parts[1].equals("Lodging")) {
lodgingTotal += Double.parseDouble(parts[2]);
}

Categories

Resources