sort line by last name and in order - java

Ok so I have this code so far that sorts by job position, now It also needs to be sort by last name and in alphabetical order. Ive managed to make it by sort by position then give the average salary and total.
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
public class faculty {
private static final String ASSISTANT = "assistant";
private static final String ASSOCIATE = "associate";
private static final String FULL = "full";
public static void main(String[] args) {
FileInputStream filestream;
BufferedReader reader;
PrintWriter writer;
String line;
double totalAssistant = 0;
double totalAssociate = 0;
double totalFull = 0;
try {
filestream = new FileInputStream("Faculty List.txt");
reader = new BufferedReader(new InputStreamReader(filestream));
writer = new PrintWriter("test.txt");
List<String> assistantList = new ArrayList<String>();
List<String> associateList = new ArrayList<String>();
List<String> fullList = new ArrayList<String>();
while ((line = reader.readLine()) != null) {
String[] split = line.split(" ");
double value = Double.parseDouble(split[split.length - 1]);
String type = split[split.length - 2];
if (ASSISTANT.equals(type)) {
assistantList.add(line);
} else if (ASSOCIATE.equals(type)) {
totalAssociate += value;
associateList.add(line);
} else if (FULL.equals(type)) {
totalFull += value;
fullList.add(line);
}
}
writeInFileOutput(writer, totalAssistant, assistantList);
writeInFileOutput(writer, totalAssociate, associateList);
writeInFileOutput(writer, totalFull, fullList);
reader.close();
writer.close();
} catch (IOException e) {
System.out.println(e);
} finally {
reader = null;
filestream = null;
writer = null;
}
}
private static void writeInFileOutput(PrintWriter writer, double totalSalary, List<String> listLines) {
for (String assistant : listLines) {
writer.append(assistant).append("\n");
}
writer.append("-------\n");
writer.append("Total Salary:$").append(String.valueOf(totalSalary)).append("\n");
writer.append("Average Salary: $")
.append(String.valueOf(totalSalary / listLines.size())).append(" \n\n");
}
}
Output
Pablo Bailey EDUC associate 68757.00
Lonnie Williamson GENS associate 134777.00
Raymond Page EDUC associate 120150.00
Wallace Fitzgerald BUSN associate 40889.00
Juana Robbins SOBL associate 93669.00
Steven Hall SOBL associate 117532.00
Melissa Davis EDUC associate 132186.00
Karla Valdez BUSN associate 16385.00
Melba Luna HLTH associate 70358.00
Sonja Washington HLTH associate 59302.00
Julio Diaz HLTH associate 102641.00
Virgil Briggs PAC associate 40936.00
Terrell Sherman EDUC associate 161595.00
Jorge Scott CSIS associate 124175.00
Tanya Duncan BUSN associate 178894.00
Troy Cannon BUSN associate 58890.00
-------
Total Salary: $3645049.0
Average Salary: $104144.25714285714
that's what my current output is, its sorted by rank. I now have to add to the list sort by last name first followed by first name alphabetically.this is just a small sample of the output cause the text file is pretty long.
The new lines can be added to the output.

I would make your stuff much more object oriented. So this means: introduce a new object employee that has some fields like following example:
public class Employee {
private String firstName;
private String familyName;
private String department;
private Enum jobPosition;
private double salary;
// Put constructor and some getters and setters for your field here
}
public enum JobPosition {
assistant,
associate,
full
}
When reading your input, split into the fields you need to create your employee and create 1 list with all your employees. Because you now have objects instead of a String containing multiple properties of one employee you can easily sort your objects on each property you want.

I'd use Aster's approach, and then either make Employee implement Comparable<Employee>, or make a Comparator<Employee>.
With Comparable<Employee>
public class Employee implements Comparable<Employee> {
#Override
public int compareTo(Employee e) {
int deptResult = this.department.compareToIgnoreCase(e.department);
if (deptResult != 0) {
return deptResult;
}
familyNameResult = this.familyName.compareToIgnoreCase(e.familyName);
if (familyNameResult != 0) {
return familyNameResult;
}
return this.firstName.compareToIgnoreCase(e.firstName);
}
}
With Comparator<Employee>
public class EmployeeComparator implements Comparator<Employee> {
#Override
public int compare(Employee e1, Employee e2) {
int deptResult = e1.getDepartment().compareToIgnoreCase(e2.getDepartment());
if (deptResult != 0) {
return deptResult;
}
familyNameResult = e1.getFamilyName().compareToIgnoreCase(e2.getFamilyName());
if (familyNameResult != 0) {
return familyNameResult;
}
return e1.getFirstName().compareToIgnoreCase(e2.getFirstName());
}
}

Related

Java: How do I iterate through a file with multiple lines, then extract specific lines after filtering delimiters?

Clarification: I have a text file with multiple lines and I want to separate specific lines into fields for an object.
I have been banging my head against a wall for about 3 days now, and I feel as if I'm overthinking this.
import java.io.*;
import java.util.*;
public class ReadFile {
public static void main(String[] args) throws FileNotFoundException {
String fileName = null;
Scanner input = new Scanner(System.in);
System.out.print("Enter file path: ");
fileName = input.nextLine();
input.close();
String fileText = readFile(fileName);
System.out.println(fileText);
}
public static String readFile(String fileName) throws FileNotFoundException {
String fileText = "";
String lineText = "";
File newFile = new File(fileName);
if (newFile.canRead()) {
try (Scanner scanFile = new Scanner(newFile)) {
while (scanFile.hasNext()) {
lineText = scanFile.nextLine();
if (lineText.startsWith("+")) {
}
else {
fileText = fileText + lineText + "\n";
}
}
} catch (Exception e) {
System.out.println(e);
}
} else {
System.out.println("No file found. Please try again.");
}
return fileText;
}
}
My goal is to take a file that looks similar to this (this is the whole file, imagine a .txt with exactly this in it):
Name of Person
----
Clothing:
Graphic TeeShirt
This shirt has a fun logo of
depicting stackoverflow and a horizon.
****
Brown Slacks
These slacks reach to the floor and
barely cover the ankles.
****
Worn Sandals
The straps on the sandals are frayed,
and the soles are obviously worn.
----
Then I need to extract the top line (e.g.: "Graphic TeeShirt") as a type of clothing the object is wearing, then "This shirt has a fun [...]" as the description of that object.
I have another .java with setters/getters/constructors, but I can't figure out how to iterate through the text file.
Edit: I know I loop through each line, but I need to create an object that has the person's name as a field, the item name (Graphic TeeShirt) as a field, then the description under the item as the next field. Then the next object will be a new object with person's name as a field, the next item (Brown Slacks) as a field, then the description as a field.
I don't know how to separate the lines in to the fields I need.
As I mentioned, the data file format is lousy, which is the real source of the problem, but your delimiters can be used to help out a little. You might approach the problem this way. Obviously don't dump your code like I've done into main but this might start you off. You still need to separate the clothing names from their descriptions but you should get the idea from the below. You can then start making a pojo out of the data.
Pass the path to your data file to this app and look out for the metadata debug outputs of 'Name' and 'Item'.
import java.util.Scanner;
import java.nio.file.Paths;
public class PersonParser {
public static void main(String[] args) {
try {
try (Scanner scPeople = new Scanner(Paths.get(args[0]))) {
scPeople.useDelimiter("----+");
int tokenCount = 0;
while (scPeople.hasNext()) {
String token = scPeople.next();
if (tokenCount % 2 == 0) {
System.out.printf("Name: %s", token);
} else {
// Parse clothing
Scanner scClothing = new Scanner(token);
scClothing.useDelimiter("\\*\\*\\*+");
while (scClothing.hasNext()) {
String item = scClothing.next();
System.out.printf("Item: %s", item);
}
}
tokenCount++;
}
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
The following code is according to the details in your question, namely:
The sample file in your question is the entire file.
You want to create instances of objects that have the following three attributes:
Person's name.
Name of an item of clothing.
Description of that item.
Note that rather than ask the user for the name of the file, I simply use a hard-coded file name. Also note that method toString, in the below code, is simply for testing purposes. The code also uses try-with-resources and method references.
public class ReadFile {
private static final String DELIM = "****";
private static final String LAST = "----";
private String name;
private String item;
private String description;
public void setName(String name) {
this.name = name;
}
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public void setDescription(String description) {
this.description = description;
}
public String toString() {
return String.format("%s | %s | %s", name, item, description);
}
public static void main(String[] strings) {
try (FileReader fr = new FileReader("clothing.txt");
BufferedReader br = new BufferedReader(fr)) {
String line = br.readLine();
String name = line;
br.readLine();
br.readLine();
line = br.readLine();
String item = line;
List<ReadFile> list = new ArrayList<>();
ReadFile instance = new ReadFile();
instance.setName(name);
instance.setItem(item);
line = br.readLine();
StringBuilder description = new StringBuilder();
while (line != null && !LAST.equals(line)) {
if (DELIM.equals(line)) {
instance.setDescription(description.toString());
list.add(instance);
instance = new ReadFile();
instance.setName(name);
description.delete(0, description.length());
}
else {
if (instance.getItem() == null) {
instance.setItem(line);
}
else {
description.append(line);
}
}
line = br.readLine();
}
if (description.length() > 0) {
instance.setDescription(description.toString());
list.add(instance);
}
list.forEach(System.out::println);
}
catch (IOException xIo) {
xIo.printStackTrace();
}
}
}
Running the above code produces the following output:
Name of Person | Graphic TeeShirt | This shirt has a fun logo ofdepicting stackoverflow and a horizon.
Name of Person | Brown Slacks | These slacks reach to the floor andbarely cover the ankles.
Name of Person | Worn Sandals | The straps on the sandals are frayed,and the soles are obviously worn.
It's not clear what you want to achieve and what is your issue exactly. You said that you can't figure out how to iterate through a text file, so let's dive into this fairly straightforward task.
In general, you have a valid, but the overcomplicated method for reading a file. Modern versions of Java provide a lot simpler methods and it's better to use them (only if you're not implementing some test task to understand how everything is working under the hood).
Please see my example below for reading a file line by line using Java NIO and Streams APIs:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Scanner;
import java.util.stream.Stream;
public class Test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter file path: ");
String fileName = input.nextLine();
input.close();
Path path = Paths.get(fileName);
try (Stream<String> lines = Files.lines(path)) {
lines.filter(line -> {
// filter your lines on some predicate
return line.startsWith("+");
});
// do the mapping to your object
} catch (IOException e) {
throw new IllegalArgumentException("Incorrect file path");
}
}
}
This should allow you to filter the lines from your files based on some predicate and later to the mapping to your POJO if you intend to do so.
If you have any other issues besides reading the file and filtering its content, please add clarification to your questions. Preferably, with examples and test data.

Java method to read text file and return ArrayList type object

public static void main(String[] args)
{
ArrayList <Locations> LocationsList = readFile("Locations.csv", "Locations");
//ArrayList <Movies> MoviesList = readFile("Movies.csv", "Movies");
//ArrayList <Operators> OperatorsList = readFile("Operators.csv", "Operators");
//ArrayList <PersonCategory> PersonCategoryList = readFile("PersonCategory.csv", "PersonCategory");
}
public static ArrayList readFile(String fileName, String whichFile)
{
ArrayList list = new ArrayList();
try
{
BufferedReader br = new BufferedReader(new FileReader(fileName));
String indata;
int line = 0;
while((indata=br.readLine())!=null)
{
StringTokenizer st = new StringTokenizer(indata,",");
if(line != 0)
{
if(whichFile.equals("Locations"))
{
int id = Integer.parseInt(st.nextToken());
String city = st.nextToken();
if(city.charAt(0) == '"')
{
String c = st.nextToken();
city = city.substring(1,city.length()) +"," +c.substring(0,c.length()-1);
}
int stateId = Integer.parseInt(st.nextToken());
Locations x = new Locations(id, city, stateId);
list.add(x);
}
else if(whichFile.equals("Movies"))
{
int id = Integer.parseInt(st.nextToken());
String name = st.nextToken();
int ratingId = Integer.parseInt(st.nextToken());
Movies x = new Movies(id, name, ratingId);
list.add(x);
}
}
line++;
}
br.close();
}
catch (FileNotFoundException fnfe){System.out.println(fnfe.getMessage());}
catch (IOException io){System.out.println(io.getMessage());}
catch (Exception e){System.out.println(e.getMessage());}
return list;
}
I'm trying to create a method that will read a text file and can return an ArrayList type object for the usage of multiple Class. With my code above, it can run successfully.
But, there are lines of warning like:
"The expression of type ArrayList needs unchecked conversion to conform to ArrayList<Locations>"
How do I fix this?
Try this.
public static <T> ArrayList<T> readFile(String fileName, Function<String[], T> converter) throws IOException {
ArrayList<T> result = new ArrayList<>();
try (BufferedReader reader = Files.newBufferedReader(Paths.get(fileName))) {
String line = reader.readLine();
String[] fields = line.split(",");
T object = converter.apply(fields);
result.add(object);
}
return result;
}
and define the converters which convert a CSV line to an object.
static Locations convertLocations(String[] fields) {
int id = Integer.parseInt(fields[0]);
String city = fields[1];
if (city.charAt(0) == '"') {
String c = fields[2];
city = city.substring(1, city.length()) + "," + c.substring(0, c.length() - 1);
}
int stateId = Integer.parseInt(fields[3]);
Locations x = new Locations(id, city, stateId);
return x;
}
static Movies convertMovies(String[] fields) {
/* Make Movies object from fields */
}
and combine them.
ArrayList<Locations> LocationsList = readFile("Locations.csv", fields -> convertLocations(fields));
ArrayList<Movies> MoviesList = readFile("Movies.csv", fields -> convertMovies(fields));
You need to create the proper generics-based ArrayList using for example: new ArrayList<Location>()
You could solve this by passing a class to readFile like this:
public static <T> ArrayList<T> readFile(....., Class<T> clazz)
{
ArrayList<T> list = new ArrayList<T>();
...
}
This is my final code that I took from #saka1029 and made some adjustments so that it will read every line in the file except the first one.
public static <T> ArrayList<T> readFile(String fileName, Function<String[], T> converter)
{
ArrayList <T> list = new ArrayList<>();
try
{
BufferedReader br = new BufferedReader(new FileReader(fileName));
br.readLine();
String inData;
while((inData=br.readLine()) != null)
{
String[] fields = inData.split(",");
T object = converter.apply(fields);
list.add(object);
}
br.close();
}
catch (FileNotFoundException fnfe){System.out.println(fnfe.getMessage());}
catch (IOException io){System.out.println(io.getMessage());}
catch (Exception e){System.out.println(e.getMessage());}
return list;
}
And this is my version of the correction of the method convertLocations from #saka1029 answer.
static Locations convertLocations(String[] fields)
{
int id = Integer.parseInt(fields[0]);
String city = fields[1];
int stateId;
if (city.charAt(0) == '"')
{
String c = fields[2];
city = city.substring(1, city.length()) + "," + c.substring(0, c.length() - 1);
stateId = Integer.parseInt(fields[3]);
}
else
stateId = Integer.parseInt(fields[2]);
Locations x = new Locations(id, city, stateId);
return x;
}
Essentially, you need to specify the type parameter for generic class ArrayList.
Since you are adding objects created from different classes to the same list, you could create an interface, say, MyInterface
public interface MyInterface {
....
}
All classes you return from readFile must implement this interface. For eg.
public class Movies implements MyInterface {
....
}
Now, you can add type parameter MyInterface at appropriate places:
public static void main(String[] args) {
ArrayList<MyInterface> LocationsList = readFile("Locations.csv", "Locations");
....
}
public static ArrayList<MyInterface> readFile(String fileName, String whichFile) {
ArrayList<MyInterface> list = new ArrayList<>();
....
}
Added below info based on reply
You may in fact choose to leave the interface blank, but then you will have to explicitly cast objects to concrete classes to do anything useful.
You could cast each object when needed
MyInterface myInterfaceObject = locationsList.get(0)
Locations locations = Locations.class.cast(myInterfaceObject);
OR
MyInterface myInterfaceObject = locationsList.get(0)
Locations locations = (Locations) myInterfaceObject;
OR You could write a list converter function for each concrete type
public class ListConverter {
public ArrayList<Locations> toLocationsArraylist(ArrayList<MyInterface> inList) {
ArrayList<Locations> outList = new ArrayList<>();
for (MyInterface listItem : inList) {
outList.add((Locations) listItem);
}
return outList;
}
}
and then
public static void main(String[] args) {
ArrayList<MyInterface> myInterfaceList = readFile("Locations.csv", "Locations");
ArrayList<Locations> locationList = ListConverter.toLocationsArraylist(myInterfaceList);
}
If you do consider using this solution, then consider renaming MyInterface more appropriately, say, to CsvRecord, or anything domain-specific.

Populate a JComboBox with an ArrayList from a different class

I'm currently stuck in this part of a class project... I need to create an ArrayList from a text file; text file has account numbers that need to be populated in a JComboBox. This is what I have so far... only the first account number populates missing the rest not sure what my mistake is
// AccountUtility class that reads file and creates ArrayList named test
public class AccountUtility {
ArrayList<String> test = new ArrayList<String>();
String[] number;
String columns[], accountNumber, customerName, openDate, balance;
int size;
public AccountUtility(){
BufferedReader in = null;
try{ // assume products.txt already exists
in = new BufferedReader(new FileReader("accounts.txt"));
String line = in.readLine();
while(line != null) {
columns = line.split("<>");
accountNumber = columns[0];
customerName = columns[1];
openDate = columns[2];
balance = columns[3];
line = in.readLine();
}
in.close();
}
catch(IOException ioe)
{
System.out.println(ioe);
}
}
public ArrayList <String> getAccountNumbers( ){
ArrayList <String> test = new ArrayList<String>();
test.add(accountNumber);
return test;
//class with JComboBox (GUI)
public class BankAccountApp extends javax.swing.JFrame {
public BankAccountApp() {
initComponents();
setLocationRelativeTo(null);
AccountUtility gc = new AccountUtility();
for( String numbers : gc.getAccountNumbers()){
accountNumberComboBox.addItem(numbers);
}
}
I would have thought that what you want is
while(line != null) {
columns = line.split("<>");
accountNumber = columns[0];
test.add(accountNumber);
....
}
and
public ArrayList getAccountNumbers( ){
return test;
}

Reading A File and Storing It In An Object

I am trying to read from a file and store the contents into an object called ToDoList(from what I assume is under the GetItem method). Then I am supposed to allow the user to add on to the list. But I am lost on how to create the object and print it.
public class ToDoList {
private ToDoItem[] items;
ToDoItem td = new ToDoItem();
String inputline;
Scanner keyboard = new Scanner(System.in);
int i = 0;
String[] stringArray = new String[100];
private void setItems(ToDoItem[] items) throws FileNotFoundException {
File file = new File("ToDoItems.txt");
Scanner ReadFile = new Scanner(file);
while (ReadFile.hasNext()) {
String ListString = ReadFile.nextLine();
stringArray[100] = (ListString);
}
}
private ToDoItem[] getItems() {
return items;
}
public void addItem(int id, String description) {
stringArray[100] = (td.getId() + td.getDescription());
}
public String[] getAddItem() throws FileNotFoundException {
try (PrintWriter fout = new PrintWriter(new File("ToDoItems.txt"))) {
do {
System.out.println("add to the list? [y/n]");
inputline = keyboard.nextLine();
if ("y".equals(inputline)) {
i++;
stringArray[i] = (td.getId() + ". " + td.getDescription() + "\n");
fout.print(stringArray[i]);
} else {
System.out.println("Here is the list so far:");
}
} while ("y".equals(inputline));
return stringArray;
}
}
#Override
public String toString() {
return "ToDoList{" + "items=" + getItems()
+ '}';
}
I am supposed to use the "getAddItem" method to allow the user to add to the list. But I can't figure out how to add an array to an object. let alone make the object.
A little code to expand on what pininfarina said and to help you get going.
You need a ToDoItem class. Something like this:
public class ToDoItem {
private String id;
private String description;
public ToDoItem(String id, String description) {
this.id = id;
this.description = description;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
Then you need a ToDoList class to hold each item. You backed yours with an Array, but I used an ArrayList:
public class ToDoList {
private ArrayList<ToDoItem> items = new ArrayList<ToDoItem>();
public ToDoList(String fileName) throws FileNotFoundException {
File file = new File(fileName);
Scanner scanner = new Scanner(file);
try {
while (scanner.hasNext()) {
String nextLine = scanner.nextLine();
StringTokenizer tokenizer = new StringTokenizer(nextLine, ",");
String id = tokenizer.nextToken();
String description = tokenizer.nextToken();
items.add(new ToDoItem(id, description));
}
} finally {
scanner.close();
}
}
public void setItems(ArrayList<ToDoItem> newItems) {
this.items.addAll(newItems);
}
public List<ToDoItem> getItems() {
return items;
}
public void addItem(ToDoItem item) {
items.add(item);
}
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("ToDoList{");
for (ToDoItem item : items) {
builder.append(item.getId() + "," + item.getDescription() + "\n");
}
builder.append("}");
return builder.toString();
}
}
This includes a constructor that reads the file and parses out items. Each line in the file must be something like "1,something" because the tokenizer uses the comma. Note that the Scanner actually destroys the file as it reads it. You might consider using some sort of FileReader instead.
Finally you need a main class to run it. Something like this:
public class RunIt {
private static Scanner keyboard = new Scanner(System.in);
public static void main(String[] args) throws FileNotFoundException {
ToDoList list = new ToDoList("ToDoItems.txt");
try (PrintWriter fout = new PrintWriter(new File("ToDoItems.txt"))) {
String inputLine;
do {
System.out.println("add to the list? [y/n]");
inputLine = keyboard.nextLine();
if ("y".equals(inputLine)) {
System.out.println("enter a to-do using the format 'id,description'");
StringTokenizer tokenizer = new StringTokenizer(keyboard.nextLine(),
",");
String id = tokenizer.nextToken();
String description = tokenizer.nextToken();
list.addItem(new ToDoItem(id, description));
} else {
System.out.println("Here is the list so far:");
System.out.println(list);
}
} while ("y".equals(inputLine));
}
}
}
Please note that there is a lot of room for improvement here (exception handling, more robust file reading, etc), but this should get you started.
You are asking a broad question. Here's some design tips for you.
Create your collection class. This could be named ToDoList. Then create the attributes and behaviors of this class. One attribute will be the collection variable of your to do list items. You can use, List, ArrayList, etc. Behaviors could be add, remove, reorder, and etc.
Create your item class. Again with the attributes and behaviors. Attributes could include what to do, date, importance level, etc.
When you read your file, have your program to instantiate your ToDoItem class for every line, item etc. then save them into the previously created container class which is your ToDoList.
You can use your ToDoList class' addItem method (behavior) to have your users add more items into your ToDoList. If you want to keep the list even after your program closes. You can create a database to store your objects.
Good luck.

How do I store information from methods to be used in another session?

So I'm making a program that will store the meetings I've had with some kids I'm tutoring. It'll keep tabs on the meeting times, discussions, and how many hours I've done. I know how to write all the methods to do that, but my issue is that the program will only hold that information for the session that the program is open... how would I go about storing this information and accessing it after the program is closed and opened again?
This is some excerpts from a test score keeper program I did in java class that has this same issue...
public class Student {
private String name;
private int test1;
private int test2;
private int test3;
public Student() {
name = "";
test1 = 0;
test2 = 0;
test3 = 0;
}
public Student(String nm, int t1, int t2, int t3){
name = nm;
test1 = t1;
test2 = t2;
test3 = t3;
}
public Student(Student s){
name = s.name;
test1 = s.test1;
test2 = s.test2;
test3 = s.test3;
}
public void setName(String nm){
name = nm;
}
public String getName (){
return name;
}
public void setScore (int i, int score){
if (i == 1) test1 = score;
else if (i == 2) test2 = score;
else test3 = score;
}
public int getScore (int i){
if (i == 1) return test1;
else if (i == 2) return test2;
else return test3;
}
public int getAverage(){
int average;
average = (int) Math.round((test1 + test2 + test3) / 3.0);
return average;
}
public int getHighScore(){
int highScore;
highScore = test1;
if (test2 > highScore) highScore = test2;
if (test3 > highScore) highScore = test3;
return highScore;
}
public String toString(){
String str;
str = "Name: " + name + "\n" + //\n makes a newline
"Test 1: " + test1 + "\n" +
"Test 2: " + test2 + "\n" +
"Test 3: " + test3 + "\n" +
"Average: " + getAverage();
return str;
}
}
If your data is not too big or complicated - something that you could save in a Rolodex in days gone by - you can save it to a file. Add methods to your class that will format the data properly and write it to a given OutputStream or Writer or whatever. And a method that will read it back.
To write to the file, add an option "save" in your program menu, and when it's chosen, open a file, iterate through your data, and call the saving method for each of your object.
To read from the file, add an option "load" in your program menu, and when it's chosen, open a file, and use your method of reading for each object.
The method for reading can be a static method in the class, that will first see if there are any data in the file and if it can read them properly, and only if it did, will create an object and return it (otherwise return null). There are other options, but this is the one that most encapsulates the needs of the object.
There is also an option to serialize and deserialize each object and put it in an object stream.
If the data is complicated, and there are many objects with various relations between them, you should use a database. This will require learning some database design and SQL.
To demonstrate the file reading/writing idea, add to your Student class:
public void save(PrintWriter outfile) {
outfile.format("%s|%d|%d|%d%n", name, test1, test2, test3);
}
This will write a line with the fields separated by "|" (vertical bar). Of course, you'll have to make sure none of the student names has a vertical bar in it. So you'll need to modify your 4-parameter constructor and your setter:
public Student(String nm, int t1, int t2, int t3) {
name = nm.replaceAll("\\|", "");
test1 = t1;
test2 = t2;
test3 = t3;
}
public void setName(String nm) {
name = nm.replaceAll("\\|", "");
}
Now, to read the file, we add a static method:
public static Student load(BufferedReader infile) throws IOException {
String line;
line = infile.readLine();
// Check if we reached end of file
if (line == null) {
return null;
}
// Split the fields by the "|", and check that we have no less than 4
// fields.
String[] fields = line.split("\\|");
if (fields.length < 4) {
return null;
}
// Parse the test scores
int[] tests = new int[3];
for (int i = 0; i < 3; i++) {
try {
tests[i] = Integer.parseInt(fields[i + 1]);
} catch (NumberFormatException e) {
// The field is not a number. Return null as we cannot parse
// this line.
return null;
}
}
// All checks done, data ready, create a new student record and return
// it
return new Student(fields[0], tests[0], tests[1], tests[2]);
}
You can see that this is more complicated, because you need to check that everything is OK at every step. In any case when things are not OK, we return null but of course, you can decide to just display a warning and read the next line. You'll have to return null when there are no more lines, though.
So, assuming we have a List<Student> students, here is how we write it to a file. I just chose "students.txt" but you can specify a full path leading where you want it. Note how I'm making a backup of the old file before I open the new file. If something goes wrong, at least you have the previous version of the file.
File f = new File("students.txt");
if (f.exists()) {
File backup = new File("students.bak");
if ( ! f.renameTo(backup) ) {
System.err.println( "Could not create backup.");
return;
}
f = new File("students.txt");
}
try ( PrintWriter outFile = new PrintWriter(f);) {
for (Student student : students) {
student.save(outFile);
}
} catch (FileNotFoundException e) {
System.err.println("Could not open file for writing.");
return;
}
After you do this, if you look for the file "students.txt", you will see the records you wrote in it.
How about reading it? Assume we have an empty students list (not null!):
try ( BufferedReader inFile = new BufferedReader(new FileReader(f))) {
Student student;
while ( ( student = Student.load(inFile)) != null) {
students.add(student);
}
} catch (FileNotFoundException e) {
System.err.println( "Could not open file for reading.");
return;
} catch (IOException e) {
System.err.println( "An error occured while reading from the file.");
}
Having done this, you can check your students list, and unless there were errors in the file, all your records will be there.
This is a demonstration, of course. You may want to read into some other collection or instead of printing an error and returning do something else. But it should give you the idea.
You could use db4o for persisting your data. Its an object-database with a spimple api to use. You can store java object read or delete them..
Download it here DB4O
And use the snippets of this tutorial (GER):Tutorial in German
Here is an example:
and Code:
package db4o.example;
public class Student {
String name;
public Student(String name) {
this.name = name;
}
#Override
public String toString() {
return "Student Name: " + name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package db4o.example;
import java.util.List;
import com.db4o.Db4oEmbedded;
import com.db4o.ObjectContainer;
public class Main {
public static void main(String[] args) {
ObjectContainer db = Db4oEmbedded.openFile("F:\\studentDB");
saveExample(db);
readAllExample(db);
readExample(db);
deleteAllExample(db);
db.close();
}
private static void deleteAllExample(ObjectContainer db) {
System.out.println("DeleteAllExample Example:");
List<Student> allStudents =readAllExample(db);
for (Student student : allStudents) {
db.delete(student);
}
db.commit();
}
private static List<Student> readAllExample(ObjectContainer db) {
System.out.println("ReadAllExample Example:");
List<Student> allStudents = db.query(Student.class);
System.out.println("Count: " + allStudents.size());
for (Student student : allStudents) {
System.out.println(student);
}
return allStudents;
}
private static void readExample(ObjectContainer db) {
System.out.println("ReadExample Example:");
Student queryStudent = new Student("Max Mustermann");
// Gets all Students named Max Mustermann
List<Student> students = db.queryByExample(queryStudent);
System.out.println("Count: " + students.size());
for (Student student : students) {
System.out.println(student);
}
}
private static void saveExample(ObjectContainer db) {
System.out.println("Save Example:");
Student myStudent = new Student("Max Mustermann");
db.store(myStudent);
db.commit();
}
}

Categories