简体   繁体   中英

Reading a special txt file in java

What I want to do is read a text file that has humans and animals. It will compile but has an error when I try to run it. I think I need a for loop to read the stringtokenizer to decipher between the human and animal in the txt file so far this is my driver class.

txt file:

Morely,Robert,123 Anywhere Street,15396,4,234.56,2
Bubba,Bulldog,58,4-15-2010,6-14-2011
Lucy,Bulldog,49,4-15-2010,6-14-2011
Wilder,John,457 Somewhere Road,78214,3,124.53,1
Ralph,Cat,12,01-16-2011,04-21-2012
Miller,John,639 Green Glenn Drive,96258,5,0.00,3
Major,Lab,105,07-10-2012,06-13-2013
King,Collie,58,06-14-2012,10-05-2012 
Pippy,cat,10,04-25-2015,04-25-2015
Jones,Sam,34 Franklin Apt B,47196,1,32.09,1
Gunther,Swiss Mountain Dog,125,10-10-2013,10-10-2013
Smith,Jack,935 Garrison Blvd,67125,4,364.00,4
Perry,Parrot,5,NA,3-13-2014
Jake,German Shepherd,86,11-14-2013,11-14-2013 
Sweetie,tabby cat,15,12-15-2013,2-15-2015
Pete,boa,8,NA,3-15-2015 

Source:

import java.util.Scanner;
import java.util.StringTokenizer;
import java.io.File;
import java.io.IOException;
/**
 * This is my driver class that reads from a txt file to put into an array and uses the class refrences so it can use the menu and spit out  
 * 
 * @author ******
 * @version 11/25/2015
 */
public class Driver
{
    /**
     * Constructor for objects of class Driver, what it does is read in the txt file gets the two class refrences and loops through to read through the whole file looking for string tokens to go to the next line
     * and closes the file at the end also uses for loop to count number of string tokens to decipher between human and pets.
     */
    public static void main(String[] args) throws IOException
    {
        Pet p;
        Human h;
        Scanner input;
        char menu;
        input = new Scanner(new File("clientdata.txt"));

        int nBalance;
        int id;

        /**
         * this while statement goes through each line looking for the string tokenizer ",". I want to count each "," to decipher between Human and Animal
         */
        while(input.hasNext())
        {
            StringTokenizer st = new StringTokenizer(input.nextLine(), ",");
            h = new Human();
            h.setLastName(st.nextToken());
            h.setFirstName(st.nextToken());
            h.setAddress(st.nextToken());
            h.setCiD(Integer.parseInt(st.nextToken()));
            h.setVisits(Integer.parseInt(st.nextToken()));
            h.setBalance(Double.parseDouble(st.nextToken()));
            p = new Pet(st.nextToken(), st.nextToken(), Integer.parseInt(st.nextToken()), st.nextToken(), st.nextToken());
        }
        /**
         * this is my seond while statement that loops the case switch statements and asks the user for client ID
         */
        menu = 'Y';
        while(menu == 'y' || menu == 'Y') {
            System.out.print("\nChose one:\n A- client names and outstanding balance \n B- client's pets, name, type and date of last visit\n C-change the client's outstanding balance: ");
            menu = input.next().charAt(0);
            System.out.print("Enter client ID: ");
            id = input.nextInt();
            h = new Human();
            if(id == h.getCiD())//if the id entered up top is equal to one of the id's in the txt file then it continues to the menu
            {
                p = new Pet();
             switch(menu)
       {    case 'A':
            System.out.println("client name: " + h.getFirstName() + "outstanding balance: " + h.getBalance());
             break;
             case 'B':
             System.out.println("pet's name: " + p.getName() + "type of pet: " + p.getTanimal() + "date of last visit: " + p.getLastVisit());
             break;
             case 'C':
             System.out.println("what do you want to change the clients balances to?");


        input.close();
       }
    }
    else// if not then it goes to this If statement saying that the Client does not exist
    { 
        System.out.println("Client does not exist.");
    }
   }
}
}

You have a number of issues you need to overcome...

  • For each line, you need to determine the type of data the line represents
  • You need some way to keep track of the data you've loaded (of the clients and their pets)
  • You need some way to associate each pet with it's owner

The first could be done in a number of ways, assuming we can change the data. You could make the first token meaningful ( human , pet ); you could use JSON or XML instead. But lets assume for the moment, you can't change the format.

The key difference between the two types of data is the number of tokens they contain, 7 for people, 5 for pets.

while (input.hasNext()) {
    String text = input.nextLine();
    String[] parts = text.split(",");
    if (parts.length == 7) {
        // Parse owner
    } else if (parts.length == 5) {
        // Parse pet
    } // else invalid data

For the second problem you could use arrays, but you would need to know in advance the number of elements you will need, the number of people and for each person, the number of pets

Oddly enough, I just noticed that the last element is an int and seems to represent the number of pets!!

Morely,Robert,123 Anywhere Street,15396,4,234.56,2
                                     ------------^

But that doesn't help us for the owners.

For the owners, you could use a List of some kind and when ever you create a new Human , you would simply add them to the List , for example...

List<Human> humans = new ArrayList<>(25);
//...
    if (parts.length == 7) {
        // Parse the properties
        human = new Human(...);
        humans.add(human);
    } else if (parts.length == 5) {

Thirdly, for the pets, each Pet should associated directly with the owner, for example:

Human human = null;
while (input.hasNext()) {
    String text = input.nextLine();
    String[] parts = text.split(",");
    if (parts.length == 7) {
        //...
    } else if (parts.length == 5) {
        if (human != null) {
            // Parse pet properties
            Pet pet = new Pet(name, type, age, date1, date2);
            human.add(pet);
        } else {
            throw new NullPointerException("Found pet without human");
        }
    }

Okay, so all this does, is each time we create a Human , we keep a reference to the "current" or "last" owner created. For each "pet" line we parse, we add it to the owner.

Now, the Human class could use either a array or List to manage the pets, either will work, as we know the expected number of pets. You would then provide getters in the Human class to get a reference to the pets.

Because out-of-context code can be hard to read, this is an example of what you might be able to do...

Scanner input = new Scanner(new File("data.txt"));
List<Human> humans = new ArrayList<>(25);
Human human = null;
while (input.hasNext()) {
    String text = input.nextLine();
    String[] parts = text.split(",");
    if (parts.length == 7) {
        String firstName = parts[0];
        String lastName = parts[1];
        String address = parts[2];
        int cid = Integer.parseInt(parts[3]);
        int vists = Integer.parseInt(parts[4]);
        double balance = Double.parseDouble(parts[5]);
        int other = Integer.parseInt(parts[6]);
        human = new Human(firstName, lastName, address, cid, vists, balance, other);
        humans.add(human);
    } else if (parts.length == 5) {
        if (human != null) {
            String name = parts[0];
            String type = parts[1];
            int age = Integer.parseInt(parts[2]);
            String date1 = parts[3];
            String date2 = parts[4];
            Pet pet = new Pet(name, type, age, date1, date2);
            human.add(pet);
        } else {
            throw new NullPointerException("Found pet without human");
        }
    }
}

What about using split() function instead of using StringTokenizer ?

Say, You can change your first while loop like below:

while (input.hasNext()) {
//  StringTokenizer st = new StringTokenizer(input.nextLine(), ",");
    String[] tokens = input.nextLine().split(",");
    if (tokens.length == 7) {
        h = new Human();
        h.setLastName(tokens[0]);
        h.setFirstName(tokens[1]);
        h.setAddress(tokens[2]);
        h.setCiD(Integer.parseInt(tokens[3]));
        h.setVisits(Integer.parseInt(tokens[4]));
        h.setBalance(Double.parseDouble(tokens[5]));
    } else {
        p = new Pet(tokens[0], tokens[1], Integer.parseInt(tokens[2]), tokens[3], tokens[4]);
    }
}

And for keeping track of which pet belongs to which human, you can append an arrayList of type Pet in Human class like below:

ArrayList<Pet> pets = new ArrayList<>();

And say you have another ArrayList of type Human named humans in the main function. So, you could append in if block like:

humans.add(h);

and in the else section, you could append in else block:

humans.get(humans.size()-1).pets.add(p);

You can try something like this - Populate a map and then using that you can assign values according to your requirement.

public void differentiate(){
    try {
        Scanner scan=new Scanner(new BufferedReader(new FileReader("//your filepath")));
            Map<String,List<String>> map=new HashMap<String, List<String>>();
            while(scan.hasNextLine()){
            List<String> petList=new ArrayList<String>();
            String s=scan.nextLine();
            String str[]=s.split(",");
            String name=str[1]+" "+str[0];
            int petCount=Integer.parseInt(str[str.length-1]);
                for(int i=1;i<=petCount;i++){
                 String petString=scan.nextLine();
                 petList.add(petString);
                }
                map.put(name, petList);
            }
            Set<String> set=map.keySet();
            for(String str:set){
                System.out.println(str+" has "+map.get(str)+" pets");
            }
        } 
        catch (FileNotFoundException e) {
        System.out.println(e.getMessage());
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM