j_fulch
j_fulch

Reputation: 125

Reading in two .txt files to match data in Java

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

Answers (3)

Drazen Bjelovuk
Drazen Bjelovuk

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

DankMemes
DankMemes

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

Tot&#242;
Tot&#242;

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

Related Questions