I'm a complete Java novice just starting to learn about collections. I'm attempting to write a program that can take a text file and create a list of objects from the contents of that file. Specifically, I have a class Students in which each student has a first name, last name, and a graduation year. The text file I'm using is of this format:
Tom Blue 2007
Richard Green 1996
Robert Black 2003
Beth White 2005
except with new lines between each student. The problem I'm getting is when I go to create my list, it appears to create a list with multiple instances of whatever the last student is in my list. For example, if I used a file with the four students above, my program creates a list with 4 copies of Beth White 2005. I'm not entirely sure what I'm doing wrong here... I don't think it's a problem with my Scanner, and I'm certain it's not a problem with my print method because I've used the default print method and the same results happen. Here's my code:
import java.io.IOException;
import java.lang.IllegalStateException;
import java.nio.file.*;
import java.util.*;
public class StudentList
{
private static Scanner input;
public static void main(String[] args)
{
Scanner keyInput = new Scanner(System.in);
System.out.println("Please enter the name of the file containing the students.");
String fileName = keyInput.next();
List<Student> studentList = new ArrayList<>(openAndReadFile(fileName));
printList(studentList);
}
private static List<Student> openAndReadFile(String fileName)
{
try
{
input = new Scanner(Paths.get(fileName));
}
catch (IOException ioException)
{
System.err.println("Error opening file. Terminating.");
System.exit(1);
}
List<Student> studentList = new ArrayList<>();
try
{
while (input.hasNext())
{
studentList.add(new Student(input.next(), input.next(), input.nextInt()));
}
}
catch (NoSuchElementException ee)
{
System.err.println("File improperly formed. Terminating.");
}
catch (IllegalStateException se)
{
System.err.println("Error reading from file. Terminating.");
}
if (input != null)
input.close();
return studentList;
}
private static void printList(List<Student> list)
{
for (Student student : list)
System.out.printf("%s%n", student);
}
}
Does the class Student use static fields by any chance?
Using static fields will cause just a single possible value to be assigned per field for all instances of the class, namely the last one assigned. If this is the case remove the static keyword so that the class fields correspond to each instance of Student
Related
I have a java problem I need to do and i'm not sure how to do it. This is the problem:
Your task is to complete the given program by writing a method named readData and a class named Person.
The readData method is written inside the Customers class. The purpose of the program is to read customer
information from a file called customers.txt, make a new object out of each customer and finally print the information of all customers on the screen.
In the file, each customer is stored on its own line. The file contains the name and social security number of each customer. The Person class has one String-type attribute that stores the person's information (name and social security number).
A toString method must be written inside the Person class, which returns the person's information. The readData method gets an array as a parameter in which the created persons are placed. The purpose of the method is to create an object out of each customer in the file and place it into the array. The method returns the number of people in the file.
That's the instruction (above) and below is the pre-made code that I can't edit (except after the "your code here" part):
import java.io.*;
import java.util.*;
import java.util.Scanner;
public class Customers {
public static void main(String[] args) throws IOException {
Person[] people = new Person[100];
int peopleAmount = readData(people);
for(int i = 0; i < peopleAmount; i++) {
System.out.println(people[i]);
}
}
// Your code here
Example output:
James 030377-2651
John 111177-1731
Robert 161280-1822
Michael 121160-1362
William 141075-16
If too busy to give a full answer, some info on how to make it is fine too. The instruction text wasn't in english originally so sorry if it has weird grammar.
Assuming that the contents of file customers.txt is the same as the example output in your question, here is my implementation. I'm guessing that you can only use classes that you have learned about and I'm also guessing that you have not yet learned about the stream API in java so hopefully the below code is acceptable within the limitations of your assignment.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Customers {
private static int readData(Person[] people) throws IOException {
int count = 0;
if (people != null && people.length > 0) {
try (FileReader fr = new FileReader("customers.txt");
BufferedReader br = new BufferedReader(fr)) {
String line = br.readLine();
while (line != null) {
String[] parts = line.split(" ");
Person p = new Person(parts[0], parts[1]);
people[count] = p;
count++;
if (count >= people.length) {
break;
}
line = br.readLine();
}
}
}
return count;
}
public static void main(String[] args) throws IOException {
Person[] people = new Person[100];
int peopleAmount = readData(people);
for(int i = 0; i < peopleAmount; i++) {
System.out.println(people[i]);
}
}
}
class Person {
String name;
String ssn;
public Person(String name, String ssn) {
this.name = name;
this.ssn = ssn;
}
public String toString() {
return name + " " + ssn;
}
}
Method readData must be a static method since it is called from method main which is a static method.
Method readData reads file customers.txt line by line. Each line contains a name followed by a single space and followed by a social security number. According to your example output both name and social security number contain no spaces. If that is not the case, then the above code will not work.
Method split will create a two element array from a line of the file. The first array element is the name and the second is the social security number. Then I create a Person object and place it in the people array.
I am writing a command line app whereby my main function creates an array list, populates it by user input, and then proceeds to add that content into a txt file. However, every time I run the main function the Array List naturally starts out empty and the data is lost from it.
The user should be able to filter their content by a specific detail(e.g all first names "jane") and have it printed to the terminal/command line. I'd like to keep the data within the file and array list constantly since I am using my getter methods to do this.
My train of thought has been to take the data stored in the file and parse it back into the array list every time the main function has been run. Given that it's a personalized list, I've had trouble doing this. Any help on an approach to help me with this task would be appreciated.
public void writeToFile(String fileName, List<Student> students) {
try {
BufferedWriter printToFile = new BufferedWriter(new FileWriter(fileName, true));
for (Student student: students) {
printToFile.write(student.toString() + "\n");
}
System.out.println("Successfully Written To File!");
printToFile.close();
}
catch (IOException Exception) {
System.out.println("Error: File Not Found");
}
}
public void openFile(String fileName) {
try{
BufferedReader reader = new BufferedReader(new FileReader(fileName));
String line;
while ((line=reader.readLine())!=null)
{
System.out.println(lin);
}
}
catch (IOException fileNotFound) {
System.out.println("File Not Found.");
}
}
What would have been quite helpful is if you also provided the Students Class code within your Posted Question but in any case.....
Apparently, earlier in your main() method you took User input to fill a List Interface of Student and then I presume you successfully wrote the contents of that List to a Text file. Keep this thought.....
The application closes. Now you restart it and now you want to refill the the List. Well, basically you just need to do pretty much exactly what you did within the main() method.
How you might do this (Not Tested!):
Make sure List<Student> students; is declared as a Class Member variable within the very same Class your main() method is located. This will make the students variable global to the entire Class (among all other things possible). Now add the following method to your main class. This method will fill the students List:
public static int loadStudentData(String fileName) {
// Create a List to hold file data;
List<String> dataList = new ArrayList<>();
// Fill The Data List.
// Use 'Try With Resources' to auto-close the BufferedReader.
try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
String line;
while ((line = reader.readLine()) != null) {
// Skip blank lines (if any);
if (line.trim().equals("")) {
continue;
}
dataList.add(line);
}
}
catch (IOException fileNotFound) {
System.out.println("File Not Found.");
}
/*
Now that you have all the Student Data from file you can
Fill in Student instance objects and add them to the students
List Object
Keep in mind, I have no idea what constructor(s) or
what Getters and Setters you have in your Student
Class OR what is contained within the data file so
we'll keep this real basic.
*/
// Declare an instance of Student.
Student student;
// Number of students to process
int studentCount = dataList.size();
// Just in case...clear the students List if it contains anything.
if (students != null || students.size() > 0) {
students.clear();
}
// Iterate through the list holding file data (dataList)
for (int i = 0; i < studentCount; i++) {
student = new Student(); // initialize a new Student
// Assuming each data line is a comma delimited string of Student data
String[] studentData = dataList.get(i).split(",|,\\s+");
student.setStudentID(studentData[0]); // String
student.setStudentName(studentData[1]); // String
student.setStudentAge(Integer.parseInt(studentData[2])); // Integer
student.setStudentGrade(studentData[3]); // String
// Add this instance of Student to the students List.
students.add(student);
}
// Return the number of students processed (just in case you want it).
return studentCount;
// DONE.
}
Note: Don't forget to close your BufferedWriter in your other *writeToFile()** method.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
Okay so I am building a program that will sort grades and records of students. It is a command-line program and when run it will start by asking for user input. there are several commands such as exit(exits program), load [file name](loads a file name), student [student name] (loads student records), etc. the others are not important. Well basically what I am wondering and what I am stuck on is all those functions will be in separate classes and will be called when the user inputs a specific command, but if I put the "load" command in its own class, then how do I get it to share its information with the other classes? I know I have to use BufferReader to read in the files, but how would I go implementing my load class, or if there is a better way feel free to say so. here is my code so far. there isn't much on my other classes because I feel like I need to figure out how to read in and share the file with the other classes first.
import java.util.*;
import java.io.*;
public class program7
{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
System.out.println("Grade Stats by ");
System.out.print(">");
while(scan.hasNextLine())
{
String input = scan.nextLine();
if(input.equals("exit"))
{
System.exit(0);
}
else if(input.equals("help"))
{
System.out.println("exit - program closes.");
System.out.println("load [filename] - loads a class database specified in [filename].");
System.out.println("students - prints out a list of students from the class, along ");
System.out.println(" with total points, and final grades for each student.");
System.out.println("assignments - prints out a list of assignments from the file, along with points possible");
System.out.println("student [student name] - Prints report for the student");
System.out.print(">");
}
else if(input.contains("load"))
{
String[] split = input.split(" ");
LoadStudents loadStudents = new LoadStudents(split[1]);
loadStudents.getFromFile();
System.out.print(">");
}
else if(input.equals("students"))
{
Students students = new Students();
students.printer();
System.out.print(">");
}
else if(input.equals("assignments"))
{
System.out.print(">");
}
else if(input.contains("student"))
{
String[] split = input.split(" ");
Student student = new Student(split[1]);
System.out.print(">");
}
else if(input.contains("assignment"))
{
}
else if(input.equals("grades"))
{
}
else
{
System.out.println("exit - program closes.");
System.out.println("load [filename] - loads a class database specified in [filename].");
System.out.println("students - prints out a list of students from the class, along ");
System.out.println(" with total points, and final grades for each student.");
System.out.println("assignments - prints out a list of assignments from the file, along with points possible");
System.out.println("student [student name] - Prints report for the student");
System.out.print(">");
}
}
}
}
That is my main class, but here is my Load and Students class.
import java.util.*;
import java.io.*;
public class LoadStudents
{
public String inputFile;
public List<Object> info = new ArrayList<Object>();
public LoadStudents(String inputFile)
{
this.inputFile = inputFile;
}
public List<Object> getFromFile()
{
try
{
BufferedReader in = new BufferedReader(new FileReader(inputFile));
try
{
String line = "";
while(in.readLine() != null)
{
line = in.readLine();
info.add(line);
}
}
catch(IOException e)
{
System.err.println("Exception, man");
}
finally
{
in.close();
}
}
catch(FileNotFoundException e)
{
System.err.println("File wasnt found ");
}
catch(IOException e)
{
System.err.println("Exception, man");
}
return info;
}
}
import java.util.*;
public class Students
{
public Students()
{
}
public void printer()
{
List<Object> info = (new LoadStudents()).getFromFile();
for (int x = 0; x<info.size(); x++)
{
System.out.println(info.get(x));
}
}
}
the Students class isnt finished but I am trying to figure out how to read the list from other classes. I have done research and have seen 3 similar problems, but they there is still something I'm missing because I keep getting the error
.\Students.java:11: error: constructor Load in class Load cannot be applied to g
iven types;
List<Object> info = (new LoadStudents()).getFromFile();
^
required: String
found: no arguments
reason: actual and formal argument lists differ in length
1 error
I understand it wants input, but I want it to use the previous input the user gives it when he inputs the command "input [whateverfile]".
Can anyone tell me how I can call that list my Load class produces to any other class?
There are many ways to do this. My suggestion is that your Load class should be a factory that actually creates a list of Student from the file, and not a list of strings.
Here are more suggestions:
Load class could have all methods statics and it could be non-instantiable. The fields you have in this class are useless after the file is read, you can just pass them to the static method as parameters.
Load is not a nice name for that class. LoadStudents is more meaningful, or even better StudentFactory.
Load and Student probably don't need to be public, package-private are be enough. Same for all the methods in these classes. Always use the lowest visibility possible.
data() is not a nice name for that method either. Something like getStudents(), or if you follow above advice, getFromFile(), is more meaningful.
Always print/log the stacktrace of the exceptions, otherwise you won't even know what/where it happened.
Instead of making the user type the whole commands, put a number on each option and let user select by number, that's faster to type and you avoid typo errors as well.
Only import the classes you're actually working with and not the whole package, that will make the compilation faster (unless you're importing a lot of classes from that package, which is not the case here).
EDIT: since you still don't understand what I mean, here's an example:
class StudentFactory {
private static List<Student> listCache = new ArrayList<>();
static List<Student> getStudents(final String filePath) {
if (listCache.isEmpty() {
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader(filePath));
String line;
while((line = in.readLine()) != null) {
// Parse the line and create a Student instance from it, then add it to the list
listCache.add(student);
}
} catch(IOException e) {
System.err.println("Exception, man");
e.printStackTrace();
} catch(FileNotFoundException e) {
System.err.println("File wasnt found ");
e.printStackTrace();
} finally {
if (in != null) in.close();
}
}
return listCache;
}
private StudentFactory() {
// Avoid instantiation
}
}
Then you can just do
final List<Student> listOfStudents = StudentFactory.getStudents(filePath);
from anywhere in your code to get a list of students. filePath can be null if you already passed it previously.
What I am trying to do exactly is creating a sorting program that sorts PatientRecords by whatever the user specifies in the command-line.
The program is operated on command-line and the user will input a text file containing the records as the first argument (args[0]), and how he wants it sorted as the second argument(args[1]).
The text file is formatted as: Lastname, Firstname, Age, Roomnumber for each line.
The amount of Lines is not specified and can vary, therefore I am using an Array list.
I can read in the lines and I got to where I could sort it by last name, but it looks like to me that the only way to do it is by separating the line at the commas and apprehending them individually in separate methods.
If there is a better way please let me know, I am open to anything. My main problem is getting the program to sort by the different categories, such as Age or RoomNumber.
Here is my code:
import java.io.*;
import java.util.*;
public class PatientRecord
{
public static void main(String args[]) {
System.out.println("Servando Hernandez");
System.out.println("Patient sorting Program.");
Scanner scan = null;
try
{
scan = new Scanner(new File(args[0]));
}
catch (FileNotFoundException e)
{
System.err.println("File path \"" + args[0] + "\" not found.");
System.exit(0);
}
ArrayList<String> lines=new ArrayList<String>();
while(scan.hasNextLine())
lines.add(scan.nextLine());
if(!(args.length == 0))
{
if(args[1] == lastname)
{
sortByLastName();
}
else if(args[1] == firstname)
{
sortByLastName();
}
else if(args[1] == age)
{
sortByAge();
}
else if(args[1] == roomnumber)
{
sortByRoomNumber();
}
}
}
static String sortByLastName()
{
Collections.sort(lines);
for(String x : lines)
System.out.println(x);
}
static String sortByFirstName()
{
}
static int sortByAge()
{
}
static int sortByRoomNumber()
{
}
}
Create a model class named Patient which has firstName, lastName etc.
class Patient{
String firstName;
String lastName;
// Constructor, getter, setter
}
I guess, text file line are comma separated. So, split the line into array and populate the List
List<Parent> patients= new ArrayList<>();
while(sc.hanNextLine()){
String[] values= sc.nextLine().split(",");
patients.add(new Patient(...))
}
Now, read the customer preferences from command line and sort the patients List.
String sortType= sc.next()
switch(sortType)){//Use java 7 or greater for string switch
case "firsname":
//Now sort the list by firstname using Comparator sort method.
break;
case "lastname":
....
}
In my Java class, we're just now learning about recursion and this is the problem that I'm asked to do. In a text file, there are several lines of employees in this format: Name,Hours,Wage,Boss.
I have a scanner set up and everything works well, except the thing is there is one main boss ("N/A" is what is under his boss field) and then it trees off into different people (in the text file they are not in order.) The task is to print them in order of ranking, ie:
BossName : Wage
--2nd Employee : Wage
----3rd Employee : Wage
-- 4th Employee : Wage
This has to be done recursively, and I'm completely stumped. I just can't find out what to put as the "base case" or how to even start it.
Thanks for any help, it's greatly appreciated.
You need to write a method which finds all employees with a given boss. Then write another method which, given a boss name and a level, finds the boss and pretty prints him/her, then finds all its employees (by calling the 1st method) and recursively calls itself for each employee.
Call this second method from main with "N/A" as the boss name and 1 as level.
well check this simple source code, maybe it will get you started...
import java.io.*;
class test
{
//main method
public static void main (String[] args) throws java.io.IOException
{
String filename = "input.txt";
// Initialize the reader
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(filename));
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
//recursive call
myRecursion(reader);
} //end main
//method using recursion to read a file
static void myRecursion(BufferedReader br)
{
String s1 = "";
try {
s1 = br.readLine();
}
catch (IOException e) {
e.printStackTrace();
}
if(s1 == null)
return;
else
{
System.out.println (s1);
myRecursion(br);
return;
}
} //end method
} //end class
The input.txt is:
one
two
three