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());
}
}
Related
I have created ArrayList. How can i use this list to get method or attribute from the class. I tried but i could not reach any solution.
I tried to get into element in array list and get some attributes but i can't.
public static void printOptions() {
System.out.println("Welcome to our university!");
System.out.println("Operations:");
System.out.println("1- College");System.out.println("a) Number of Departments");System.out.println("b) Number of Courses");System.out.println("c) Number of Professors");System.out.println("d) Number of Students");System.out.println("e) Report");
System.out.println("2- Department");System.out.println("a) New");System.out.println("b) Number of Courses");System.out.println("c) Number of Students");System.out.println("d) Is Full");System.out.println("e) Enroll");System.out.println("f) Report");
System.out.println("3- Course");System.out.println("a) New");System.out.println("b) Number of Students");System.out.println("c) Assign");System.out.println("d) Is assigned");System.out.println("e) Professor Name");System.out.println("f) Is Full");System.out.println("g) Enroll");System.out.println("h) Report");
System.out.println("4- Professor");System.out.println("a) New");System.out.println("b) Display Salary");System.out.println("c) Get Raise");System.out.println("d) Report");
System.out.println("5- Student");System.out.println("a) New");System.out.println("b) Report");
System.out.println("6- Quit");
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
printOptions() ;
List<Department> departmentList;departmentList = new ArrayList<>();
List<Course> courseList ;courseList = new ArrayList<>();
List<Professor> proffList = new ArrayList<>() ;
List<Student> studentList;studentList = new ArrayList<>() ;
Scanner in = new Scanner(System.in) ;
int d = 0 , c = 0 , p = 0 , s=0 ;
College AinShams = new College() ;
while (true){
String option = in.nextLine() ;
if(!"6".equals(option)) {
if ("2a".equals(option)) { // Define new department
System.out.println("Department Name:");
String depName = in.nextLine() ;
System.out.println("Department Description:");
String depDescripe = in.nextLine() ;
System.out.println("Department Max Students:");
int max_num = in.nextInt() ;
in.nextLine() ;
Department Department_Name = new Department(depName, depDescripe, max_num);
// departmentList.add(Department_Name);
departmentList.add(d, Department_Name);
d++ ;
AinShams.setDepart(departmentList);
}
else if ("4a".equalsIgnoreCase(option)) {//new proff
System.out.println("Professor Firstname:");
String firstName = in.nextLine() ;
System.out.println("Professor Lastname:");
String lastName = in.nextLine();
System.out.println("Professor telephone:");
String telephone = in.nextLine();
System.out.println("Professor address:");
String address = in.nextLine();
System.out.println("Professor salary:");
double salary = in.nextDouble() ;
Professor proff = new Professor(firstName, lastName, telephone, address, salary);
proffList.add(p,proff) ;
p++ ;
AinShams.setProf(proffList);
}
else if ("2e".equalsIgnoreCase(option)) {//add student in department
System.out.println("Department:");
String dep= in.nextLine() ;
System.out.println("Student:");
String stu= in.nextLine();
// System.out.println(AinShams.getDepart());
AinShams.getDepart().
/*for (int i = 0; i < AinShams.getDepart().size(); i++) {
}*/
}
System.out.println("============");
System.out.println("Enter Operation");
System.out.println("============");
}else {break ;}
}
}
}
In condition (2e), I need to get methods and attributes in class which I assigned in array List
AinShams.getDepart() is referring to an object which you defined as data type College:
College AinShams = new College();
The rest of the College code is not in this fragment so I cannot tell whether the .getDepart() method exists. Either way, the College is not an ArrayList.
If you want to reach the methods and fields of objects inside an ArrayList something like the following would work. As an example I take the ArrayList called departmentlist, and use the get() method to return the 0th element from that list. Assuming the 0th element of that class is an object of type Department, the .name asks for the name field (again, assuming this name variable exists in the Department class). The .getName() would be a better way to get the name value but requires you coding this method in the Department class.
departmentlist.get(0).name
departmentlist.get(0).getName()
By the way, consider reducing some of the "System.out.println()" clutter in the top of your code by formatting your output with the "\n" new line key. Try these two examples using 1 system.out.println call to print two lines of text:
System.out.println("Welcome to our university!" + "\n" + "Operations:");
System.out.println("Welcome to our university! \nOperations:");
You want to add a new student to a department. Your College class has other attributes like list of departments, professors, etc.
Approach:
You can get the Department object from the array list, by the department name (property) passed by the user in case-2e. Then use that object to insert new student to its student's list.
Code:
Your code can be something like below (Pardon any compilation error as I haven't used any IDE. Follow the approach):
String dept = in.nextLine();
Department department = AinShams.getDepart().stream().filter(department -> department.getName().contentEquals(dept)).limit(1);
department.getStudentList().add(new Student());
Follow the link for non-stream version:
How to find an object in an ArrayList by property
OR Use the following method:
Department findDepartment(List<Department> deptList, String dept) {
for(Department department : deptList) {
if(department.getName().equals(dept)) {
return department;
}
}
return null;
}
I have three input fields.
First Name
Last item
Date Of Birth
I would like to get random data for each input from a property file.
This is how the property file looks. Field name and = should be ignored.
- First Name= Robert, Brian, Shawn, Bay, John, Paul
- Last Name= Jerry, Adam ,Lu , Eric
- Date of Birth= 01/12/12,12/10/12,1/2/17
Example: For First Name: File should randomly select one name from the following names
Robert, Brian, Shawn, Bay, John, Paul
Also I need to ignore anything before =
FileInputStream objfile = new FileInputStream(System.getProperty("user.dir "+path);
in = new BufferedReader(new InputStreamReader(objfile ));
String line = in.readLine();
while (line != null && !line.trim().isEmpty()) {
String eachRecord[]=line.trim().split(",");
Random rand = new Random();
//I need to pick first name randomly from the file from row 1.
send(firstName,(eachRecord[0]));
If you know that you're always going to have just those 3 lines in your property file I would get put each into a map with an index as the key then randomly generate a key in the range of the map.
// your code here to read the file in
HashMap<String, String> firstNameMap = new HashMap<String, String>();
HashMap<String, String> lastNameMap = new HashMap<String, String>();
HashMap<String, String> dobMap = new HashMap<String, String>();
String line;
while (line = in.readLine() != null) {
String[] parts = line.split("=");
if(parts[0].equals("First Name")) {
String[] values = lineParts[1].split(",");
for (int i = 0; i < values.length; ++i) {
firstNameMap.put(i, values[i]);
}
}
else if(parts[0].equals("Last Name")) {
// do the same as FN but for lastnamemap
}
else if(parts[0].equals("Date of Birth") {
// do the same as FN but for dobmap
}
}
// Now you can use the length of the map and a random number to get a value
// first name for instance:
int randomNum = ThreadLocalRandom.current().nextInt(0, firstNameMap.size(0 + 1);
System.out.println("First Name: " + firstNameMap.get(randomNum));
// and you would do the same for the other fields
The code can easily be refactored with some helper methods to make it cleaner, we'll leave that as a HW assignment :)
This way you have a cache of all your values that you can call at anytime and get a random value. I realize this isn't the most optimum solution having nested loops and 3 different maps but if your input file only contains 3 lines and you're not expecting to have millions of inputs it should be just fine.
Haven't programmed stuff like this in a long time.
Feel free to test it, and let me know if it works.
The result of this code should be a HashMap object called values
You can then get the specific fields you want from it, using get(field_name)
For example - values.get("First Name"). Make sure to use to correct case, because "first name" won't work.
If you want it all to be lower case, you can just add .toLowerCase() at the end of the line that puts the field and value into the HashMap
import java.lang.Math;
import java.util.HashMap;
public class Test
{
// arguments are passed using the text field below this editor
public static void main(String[] args)
{
// set the value of "in" here, so you actually read from it
HashMap<String, String> values = new HashMap<String, String>();
String line;
while (((line = in.readLine()) != null) && !line.trim().isEmpty()) {
if(!line.contains("=")) {
continue;
}
String[] lineParts = line.split("=");
String[] eachRecord = lineParts[1].split(",");
System.out.println("adding value of field type = " + lineParts[0].trim());
// now add the mapping to the values HashMap - values[field_name] = random_field_value
values.put(lineParts[0].trim(), eachRecord[(int) (Math.random() * eachRecord.length)].trim());
}
System.out.println("First Name = " + values.get("First Name"));
System.out.println("Last Name = " + values.get("Last Name"));
System.out.println("Date of Birth = " + values.get("Date of Birth"));
}
}
I have a class called CD with the following private variables:
private String artist = "";
private String year = "";
private String albumName = "";
private ArrayList<String> songs = new ArrayList<String>();
This class is used to store input data that is in this format:
Led Zeppelin
1979 In Through the Outdoor
-In the Evening
-South Bound Saurez
-Fool in the Rain
-Hot Dog
-Carouselambra
-All My Love
-I'm Gonna Crawl
I have a CDParser class that is in charge of parsing the file called sample.db line by line to store it into our CD object. After parsing, the CD object, after initializing it with CD newCD = new CD() has the following structure:
artist = "Led Zeppelin"
year = "1979"
albumName = "In Through the Outdoor"
songs = {"-In the Evening", "-South Bound Saurez", "-Fool in the Rain", "-Hot Dog"}
Now.. For this project, sample.db contains many albums, which looks like the following:
Led Zeppelin
1979 In Through the Outdoor
-In the Evening
-South Bound Saurez
-Fool in the Rain
-Hot Dog
-Carouselambra
-All My Love
-I'm Gonna Crawl
Led Zeppelin
1969 II
-Whole Lotta Love
-What Is and What Should Never Be
-The Lemon Song
-Thank You
-Heartbreaker
-Living Loving Maid (She's Just a Woman)
-Ramble On
-Moby Dick
-Bring It on Home
Bob Dylan
1966 Blonde on Blonde
-Rainy Day Women #12 & 35
-Pledging My Time
-Visions of Johanna
-One of Us Must Know (Sooner or Later)
-I Want You
-Stuck Inside of Mobile with the Memphis Blues Again
-Leopard-Skin Pill-Box Hat
-Just Like a Woman
-Most Likely You Go Your Way (And I'll Go Mine)
-Temporary Like Achilles
-Absolutely Sweet Marie
-4th Time Around
-Obviously 5 Believers
-Sad Eyed Lady of the Lowlands
I have so far been able to parse all three different albums and save them into my CD object, but ran into a roadblock where I'm simply saving all three albums into the same newCD object.
My question is - is there a way of programmatically initialize my CD constructor that will follow the format newCD1, newCD2, newCD3, etc, as I parse the sample.db?
What this means is, as I parse this particular file:
newCD1 would be the album In Through the Outdoor (and its respective private vars)
newCD2 would be the album II (and its respective private vars)
newCD3 would be the album Blonde on Blonde, and so on
Is this a smart way to do it? Or could you suggest me a better way?
EDIT:
Attached is my parser code. ourDB is an ArrayList containing every line of sample.db:
CD newCD = new CD();
int line = 0;
for(String string : this.ourDB) {
if(line == ARTIST) {
newCD.setArtist(string);
System.out.println(string);
line++;
} else if(line == YEAR_AND_ALBUM_NAME){
String[] elements = string.split(" ");
String[] albumNameArr = Arrays.copyOfRange(elements, 1, elements.length);
String year = elements[0];
String albumName = join(albumNameArr, " ");
newCD.setYear(year);
newCD.setAlbumName(albumName);
System.out.println(year);
System.out.println(albumName);
line++;
} else if(line >= SONGS && !string.equals("")) {
newCD.setSong(string);
System.out.println(string);
line++;
} else if(string.isEmpty()){
line = 0;
}
}
You have a single CD object, so you keep overwriting it. Instead, You could hold a collection of CDs. E.g.:
List<CD> cds = new ArrayList<>();
CD newCD = new CD();
int line = 0;
for(String string : this.ourDB) {
if(line == ARTIST) {
newCD.setArtist(string);
System.out.println(string);
line++;
} else if(line == YEAR_AND_ALBUM_NAME){
String[] elements = string.split(" ");
String[] albumNameArr = Arrays.copyOfRange(elements, 1, elements.length);
String year = elements[0];
String albumName = join(albumNameArr, " ");
newCD.setYear(year);
newCD.setAlbumName(albumName);
System.out.println(year);
System.out.println(albumName);
line++;
} else if(line >= SONGS && !string.equals("")) {
newCD.setSong(string);
System.out.println(string);
line++;
} else if(string.isEmpty()){
// We're starting a new CD!
// Add the one we have so far to the list, and start afresh
cds.add(newCD);
newCD = new CD();
line = 0;
}
}
// Take care of the case the file doesn't end with a newline:
if (line != 0) {
cds.add(newCD);
}
The problem is that you're using the same object reference of CD to fill the values of the parse of the file.
Just make sure to initialize and store every instance of CD newCD every time you start parsing the content of a new album.
You may do the following:
List<CD> cdList = new ArrayList<>();
for (<some way to handle you're reading a new album entry from your file>) {
CD cd = new CD();
//method below parses the data in the db per album entry
//an album entry may contain several lines
parseData(cd, this.ourDB);
cdList.add(cd);
}
System.out.println(cdList);
Your current way to parse the file works but is not as readable as it should be. I would recommend using two loops:
List<CD> cdList = new ArrayList<>();
Iterator<String> yourDBIterator = this.ourDB.iterator();
//it will force to enter the first time
while (yourDBIterator.hasNext()) {
//do the parsing here...
CD cd = new CD();
//method below parses the data in the db per album entry
//an album entry may contain several lines
parseData(cd, yourDBIterator);
cdList.add(cd);
}
//...
public void parseData(CD cd, Iterator<String> it) {
String string = it.next();
int line = ARTIST;
while (!"".equals(string)) {
if (line == ARTIST) {
newCD.setArtist(string);
System.out.println(string);
line++;
} else if(line == YEAR_AND_ALBUM_NAME){
String[] elements = string.split(" ");
String[] albumNameArr = Arrays.copyOfRange(elements, 1, elements.length);
String year = elements[0];
String albumName = join(albumNameArr, " ");
newCD.setYear(year);
newCD.setAlbumName(albumName);
System.out.println(year);
System.out.println(albumName);
line++;
} else if(line >= SONGS && !string.equals("")) {
newCD.setSong(string);
System.out.println(string);
line++;
}
if (it.hasNext()) {
string = it.next();
} else {
string = "";
}
}
}
Then, your code
I suggest to use the Builder design pattern to construct the CD object. If you read lines always in the same order, it will be not complicated to implement and use. Good tutorial: http://www.javacodegeeks.com/2013/01/the-builder-pattern-in-practice.html
Pretty much for my assignment I have to List all the courses (just the course code) that have classes in a given building on a given day such that any part of the class is between the given times. Each course involved should only be listed once, even if it has several classes. I have done everything except listing the course once, even if it has several classes. How do I ignore duplicate strings from a file?
public void potentialDisruptions(String building, String targetDay, int targetStart, int targetEnd){
UI.printf("\nClasses in %s on %s between %d and %d%n",
building, targetDay, targetStart, targetEnd);
UI.println("=================================");
boolean containsCourse = false;
try {
Scanner scan = new Scanner(new File("classdata.txt"));
while(scan.hasNext()){
String course = scan.next();
String type= scan.next();
String day = scan.next();
int startTime = scan.nextInt();
int endTime = scan.nextInt();
String room = scan.next();
if(room.contains(building)){
if(day.contains(targetDay)){
if(endTime >= targetStart){
if( startTime<= targetEnd){
UI.printf("%s%n", course);
containsCourse = true;
}
}
}
}
}
if(!containsCourse){
UI.println("error");
}
}
catch(IOException e){
UI.println("File reading failed");
}
UI.println("=========================");
}
You can put all the string token in Set and check if that token contain in Set befor you process further as below :-
// Declration
....
Set courseSet = new HashSet();
...
// Check befor you process further
if(!courseSet.contains(course))
{
...
// Your Code...
...
courseSet.add(course)
}
You could put the courses in a Set and loop over them since a Set always contains unique values.
I am working on a code that reads data about customers from an input file and stores them into a linkedlist of objects of customer. the linked list implementation is not the JVM one. while reading the data using the readFile(), it's giving me a NumberFormatException: For input string: "Ben Affleck" error. here's the method. the basic idea of the logic is to read the first record initially and set it as the head of the linked list and then read the subsequent records. the error occurs during the if conditional when it checks for duplicate account id's. the way i coded it was if the id's match then skip those many number of lines to the next record. the Acd() method enters items in ascending order in the linkedlist. help would be greatly appreciated. kindly let me know if the question is unclear.
public static int readFile(String filename, LinkedList<Customer> review) throws IOException{
Scanner scan = new Scanner (new File (filename));
/*Reading the first record separatly*/
Customer head = new Customer();
Node<Customer> first = new Node<Customer>(head);
String[] a = scan.nextLine().split("=");
int accId = Integer.parseInt(a[1].trim());
a = scan.nextLine().split("=");
String name = a[1].toUpperCase().trim();
a = scan.nextLine().split("=");
String address =a[1].trim();
a = scan.nextLine().split("=");
String phone_number =(a[1].trim());
a = scan.nextLine().split("=");
String date_of_birth =(a[1].trim());
a = scan.nextLine().split("=");
double balance =(Double.parseDouble(a[1].trim()));
a= scan.nextLine().split("=");
String accType =(a[1].trim());
if (accType.equals("Saving")){
Customer temp = new Account1();
Node<Customer> firstItem = new Node<Customer>(temp);
first = firstItem;
}
else if(accType.equals("Checking")){
Customer temp = new Account2();
Node<Customer> firstItem = new Node<Customer>(temp);
first = firstItem;
}
else if(accType.equals("Fixed")){
Customer temp = new Account3();
Node<Customer> firstItem = new Node<Customer>(temp);
first = firstItem;
a = scan.nextLine().split("=");
((Account3)first.item).set_intRate(Double.parseDouble(a[1].trim()));
}
first.item.set_account_id(accId);
first.item.set_name(name);
first.item.set_address(address);
first.item.set_phone_number(phone_number);
first.item.set_date_of_birth(date_of_birth);
first.item.set_balance(balance);
review.head= first;
count = count+1;
scan.nextLine();// resets the buffer reader
while (scan.hasNext()&& count>0){
Customer item = new Customer();
Node<Customer> temp = new Node<Customer>(item);
String[] st = scan.nextLine().split("=");
Customer ctr = new Customer();
Node<Customer> counter = new Node<Customer>(ctr);
counter=review.head; // counter pointing to head
int i=0;
while(counter!=null){
if(Integer.parseInt(st[1].trim())== review.getItem(i).get_accountid()){ // checking for duplicate records
System.out.println("This account id is already in use so the record won't be read");
while(!scan.nextLine().equals(" "))
scan.nextLine();
scan.nextLine(); //to bring the reader back to the accoutnId
}
else
break;
int AccId = Integer.parseInt(st[1].trim());
st = scan.nextLine().split("=");
String AccName = st[1].toUpperCase().trim();
st = scan.nextLine().split("=");
String AccAdd =st[1].trim();
st = scan.nextLine().split("=");
String AccPhNum =(st[1].trim());
st = scan.nextLine().split("=");
String AccDob =(st[1].trim());
st = scan.nextLine().split("=");
double AccBal =(Double.parseDouble(st[1].trim()));
st= scan.nextLine().split("=");
String AccType =(st[1].trim());
if (AccType.equals("Saving")){
Customer a1 = new Account1();
Node<Customer>Item = new Node<Customer>(a1);
temp = Item;
} else if(AccType.equals("Checking")){
Customer a2 = new Account2();
Node<Customer>Item = new Node<Customer>(a2);
temp = Item;
} else if(AccType.equals("Fixed")){
Customer a3 = new Account3();
Node<Customer>Item = new Node<Customer>(a3);
temp = Item;
st = scan.nextLine().split("=");
((Account3)temp.item).set_intRate(Double.parseDouble(a[1].trim()));
}
temp.item.set_account_id(AccId);
temp.item.set_name(AccName);
temp.item.set_address(AccAdd);
temp.item.set_phone_number(AccPhNum);
temp.item.set_date_of_birth(AccDob);
temp.item.set_balance(AccBal);
if (scan.hasNextLine()){
scan.nextLine();
}
review.insertAcd(temp.item);
count= count+1;
counter=counter.next;
}
if (count>=30){
System.out.println("The number of records read has exceeded the limit and it will stop reading now");
break;
}
}
return count;
}
The input file is:
Account Id = 123
Name = Matt Damon
Address = 465 Ripley Boulevard, Oscar Mansion, Singapore 7666322
DOB = 10-10-1970
Phone Number = 790-3233
Account Balance = 405600.00
Account Type = Fixed
Fixed Daily Interest = 0.05
Account Id = 126
Name = Ben Affleck
Address = 200 Hunting Street, Singapore 784563
DOB = 25-10-1968
Phone Number = 432-4579
Account Balance = 530045.00
Account Type = Saving
Account Id = 65
Name = Salma Hayek
Address = 45 Mexican Boulevard, Hotel California, Singapore 467822
DOB = 06-04-73
Phone Number = 790-0000
Account Balance = 2345.00
Account Type = Checking
Account Id = 78
Name = Phua Chu Kang
Address = 50 PCK Avenue, Singapore 639798
DOB = 11-08-64
Phone Number = 345-6780
Account Balance = 0.00
Account Type = Checking
Account Id = 234
Name = Zoe Tay
Address = 100 Blue Eyed St, Singapore 456872
DOB = 15-02-68
Phone Number = 456-1234
Account Balance = 600.00
Account Type = Saving
Account Id = 2350
Name = Zoe Tay
Address = 100 Blue Eyed St, Singapore 456872
DOB = 15-02-68
Phone Number = 456-1234
Account Balance = 600.00
Account Type = Fixed
Fixed Daily Interest = 0.055
The first record has more lines (it has a "Fixed Daily Interest") than the second, so you may think you are reading in a String but it is actually a Double (or vice versa). So you will need to modify your code to either take into consideration this extra line or remove it from the first record as your code is expecting int, String, String, String, String, double, String whereas the first record is int, String, String, String, String, double, String, double.
This is not really the optimum solution to this problem, as you are repeating a chunk of code. It really could be in a single loop I think. It is definitely a type conversion problem like I initially said. You are attempting to get an integer out of a String that does not contain a number. Java is correctly telling you that there is no parsable Integer.
I will try and compile your code and see if I can pinpoint the exact error but what I have written above should give you enough of an idea to find out where the breakage is. Basically you think you are reading one line of your input file whereas you are actually on the line above or below.
Edit: Well I've hacked up your code and got it to compile. From an initial inspection it looks like that Matt Damon is OK but it is the second loop that is incorrect. You have an code that looks like this:
while (scan.hasNext()&& count>0){
Customer item = new Customer();
Node<Customer> temp = new Node<Customer>(item);
String[] st = scan.nextLine().split("=");
....
while(counter!=null){
if(Integer.parseInt(st[1].trim())== review.getItem(i).get_accountid()){
...
} else {
break;
}
}
}
The account number st[1].trim() (this is 126 from your input file by the way) does not match since Matt Damon is the only one so far, so the code breaks out of the inner while condition and then proceeds to read the next line - "Ben Affleck". Then it enters the inner while loop again and tried to do Integer.parseInt on "Ben Affleck" which as you see is a NumberFormatException.
Edit 2:
Having looked over your other questions it looks like you are getting the SO community to write a lot of the application for you! It is clear you are learning Java but this may not be the best way to learn Java in my opinion! Don't worry though, we've all been there :-)
Without stepping through your exact code I cannot really answer the question exactly. Note that it cannot be compiled standalone the form given above since it is missing dependent classes, a main() and import statements.
So my answer is going to be mostly pseudocode for your entire readFile function since I see no reason why the first record should be read in separately and I think the function is overly complex for what it needs to do.
Scanner scan = new Scanner (new File (filename));
// maintain collecction of Account Number <-> Account details
Map<Integer, Customer> accounts = new HashMap<Integer, Customer>();
String[] aLine = null;
while (scan.hasNext()) {
// read all of one account details
aLine= scan.nextLine().split("=");
int accId = Integer.parseInt(aLine[1].trim());
aLine= scan.nextLine().split("=");
String name = aLine[1].toUpperCase().trim();
etc...
String accType =(a[1].trim());
if (accType.equals("Saving")) {
...
} else {
...
}
// create Integer version of the accId to use as the key (the lookup)
// into the collection of details
Integer key = new Integer(accId);
if (accounts.containsKey(key)) {
// already added to the collection so
// no need to create a new Customer
} else {
// create new Customer
Customer c = new Customer();
c.set_account_id(accId);
etc...
// and add to the collection
c.put(key, c);
}
// skip over blank lines
while(!scan.nextLine().equals(" ")) {
scan.nextLine();
}
}
You may want to add some constraints to the while condition to limit the number of accounts added (as you have that in your existing code). For example:
while (scan.hasNext() && accounts.size() < 30) {
Hope this helps!