Reputation: 125
I'm working on a school project and for the class I am supposed to read in two different .txt files. From the files I am supposed use the data to analyses it. And print out nicely some analyzed information. Specifically I have a .txt file with a list of userID numbers and first names. It looks like this:
1,Bobby
2,Joe
3,Sue
4,Mary
5,Victor
From that I have another .txt file that holds the data. It looks like this:
1,452,2127
2,500,1482
2,462,2490
3,172,2706
The first number is the customer ID that links to the other file the second is the number of min, the third is the number of text messages.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class CustomerDriver2 {
public static void main(String[] args) throws FileNotFoundException {
File custFile = new File("Customers.txt");
Scanner custScanner = new Scanner(custFile);
File usageFile = new File("CellPhoneUsage.txt");
Scanner usageScanner = new Scanner(usageFile);
int custID = 0;
int custID2 = 0;
String name = "";
Customer myCustomer = new Customer(0, "");
while(custScanner.hasNextLine())
{
String myLine = custScanner.nextLine();
Scanner myLineScan = new Scanner(myLine);
myLineScan.useDelimiter(",");
while(myLineScan.hasNext())
{
custID = myLineScan.nextInt();
name = myLineScan.nextLine();
myCustomer = new Customer(custID, name);
while(usageScanner.hasNextLine())
{
String myLine2 = usageScanner.nextLine();
Scanner myLineScan2 = new Scanner(myLine2);
myLineScan2.useDelimiter(",");
while (myLineScan2.hasNext())
{
custID2 = myLineScan2.nextInt();
int calls = myLineScan2.nextInt();
int txt = myLineScan2.nextInt();
if(custID == custID2)
{
myCustomer.setMinTotal(calls);
myCustomer.setTxtTotal(txt);
}
}
}
System.out.println(myCustomer.toString());
}
}
}//end of main
}//end of class
With what I currently have I get an output like this:
Name: ,Bobby
Min Sum: 3509
Text Sum: 21370
Min Average: 350
Txt Average: 2137
Name: ,Joe
Min Sum: 0
Text Sum: 0
Min Average: 0
Txt Average: 0
Name: ,Sue
Min Sum: 0
Text Sum: 0
Min Average: 0
Txt Average: 0
Name: ,Mary
Min Sum: 0
Text Sum: 0
Min Average: 0
Txt Average: 0
Name: ,Victor
Min Sum: 0
Text Sum: 0
Min Average: 0
Txt Average: 0
It is getting the name right, but its not getting the data correctly. I'm so confused as to where I went wrong.
What I need is for the other 4 names to also have the type of data that the first one has.
I also have another class called Customer that does the calculations:
public class Customer {
int custID;
String name;
int totalMin;
int totalTxt;
//constructor
public Customer(int custID, String name)
{
this.custID = custID;
this.name = name;
}
public Customer(int custID, int totalMin, int totalTxt)
{
this.custID = custID;
this.totalMin = totalMin;
this.totalTxt = totalTxt;
}
public void setMinTotal(int min)
{
this.totalMin = totalMin + min;
}
public void setTxtTotal(int txt)
{
this.totalTxt = totalTxt + txt;
}
public int getAvgMin()
{
return totalMin/10;
}
public int getAvgTxt()
{
return totalTxt/10;
}
public String toString()
{
return "Name: " + name + "\n"
+ "Min Sum: " + totalMin +"\n"
+ "Text Sum: "+ totalTxt + "\n"
+ "Min Average: " + getAvgMin() + "\n"
+ "Txt Average: " + getAvgTxt()+ "\n";
}
}
Upvotes: 0
Views: 1338
Reputation: 5482
Late to the party, but here's a solution to avoid over-using the scanner.
public static void main(String[] args) throws FileNotFoundException {
File custFile = new File("Customers.txt");
Scanner custScanner = new Scanner(custFile);
File usageFile = new File("CellPhoneUsage.txt");
Scanner usageScanner = new Scanner(usageFile);
ArrayList<Customer> customers = new ArrayList<Customer>();
ArrayList<Usage> usages = new ArrayList<Usage>();
//begins customer scanning
while (custScanner.hasNextLine()) {
String myLine = custScanner.nextLine();
Scanner myLineScan = new Scanner(myLine);
myLineScan.useDelimiter(",");
while (myLineScan.hasNext()) {
int custID = myLineScan.nextInt();
String name = myLineScan.nextLine();
customers.add(new Customer(custID, name));
}
}
//begins usage scanning
while (usageScanner.hasNextLine()) {
String myLine2 = usageScanner.nextLine();
Scanner myLineScan2 = new Scanner(myLine2);
myLineScan2.useDelimiter(",");
while (myLineScan2.hasNext()) {
int custID = myLineScan2.nextInt();
int calls = myLineScan2.nextInt();
int txt = myLineScan2.nextInt();
usages.add((new Usage(custID, calls, txt)));
}
}
for (Customer customer : customers) {
// Iterator to remove matching usage data while iterating
// (more efficient in that it avoids needlessly looping over
// usages that have already been applied)
Iterator<Usage> i = usages.iterator();
while (i.hasNext()) {
Usage usage = i.next();
if (usage.custID == customer.custID) {
customer.setMinTotal(usage.calls);
customer.setTxtTotal(usage.txts);
i.remove();
}
}
System.out.println(customer.toString());
}
}
Simple Usage class:
class Usage {
int custID;
int calls;
int txts;
Usage(int custID, int calls, int txts) {
this.custID = custID;
this.calls = calls;
this.txts = txts;
}
}
Upvotes: 0
Reputation: 2137
Your problem is that in your first while(myLineScan.hasNext())
loop you are reassigning a variable multiple times and then just using the first value. Basically, it looks like this:
Initially, custID=0 and name=""
Enter loop
read line, going with your provided input, custID is now 1 and name is "Bobby"
Loop again, read next line. custID is now 2 and name is "Joe"
**** this is where you lose your data; the original id 1 and name "Bobby" are now lost and won't be processed
Repeat for all names, throwing them all out
You are left with just the last line's custID and name
Your code goes on to parse only that data
See what the problem is? You need to manage ALL the data you parse in the first loop instead of throwing it away. I recommend you use a HashMap
to link customer ids to names. So in your first loop do something like
Map<Integer, String> idsToNames=new HashMap<>(); // create a map of ids to names
while(myLineScan.hasNext()) {
int theId = myLineScan.nextInt();
String theName = myLineScan.nextLine();
idsToNames.put(theId, theName);
}//end while loop
// Then later retrieve data based on id like this:
int idYouWantToFind=//whatever
String nameCorrespondingToThatId=idsToNames.get(idYouWantToFind);
Note that in HashMaps and other generic classes you will need to specify Integer as a generic parameter, not int. Same goes for Float, Char, Byte, and all other primitives. Java will automatically take care of converting ints to Integers, etc. More info here: http://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#instantiate
Upvotes: 0
Reputation: 1854
I think your problem is
while(usageScanner.hasNextLine())
{
String myLine2 = usageScanner.nextLine();
.....
After you fully iterate over that lines (which happens for the first customer), this will always return false.
You have to rewrite some of the code to solve it.
You can 1. Instantiate a new scanner on every loop (very resource expensive) 2. Parse that file separately and store customer id and data in a list of separate objects, than when iterating over the customer pull the data from that list
EDIT
This is my solution 1 (quick to be implemented but resource expensive). You have to instantiate a new usage scanned every time inside the 1st loop
Change
File usageFile = new File("CellPhoneUsage.txt");
//Scanner usageScanner = new Scanner(usageFile);
...
while(custScanner.hasNextLine())
{
Scanner usageScanner = new Scanner(usageFile);
Upvotes: 1