what I have here is a set of three ArrayLists. An ArrayList of students which holds the name , surname , uid and degree scheme. Then I also have a list of modules and each module also holds an arraylist of student ID's for the students which are enrolled on that particular module.
What I'm trying to do is to link in the arraylist of students with the arraylist of the user ID's so the program would look at the ID's and compare them to the list which has all the student details and then write a combined report with the full student details and the modules which they are enrolled on.
I'm having my arraylists set up nicely, but I'm having difficulty accessing the inner arraylist with the ID's. It's quite tricky to explain but here is the code for my Application class that holds everything together, you can see how the ArrayLists are laid out.
import java.util.*;
import java.io.*;
public class Model {
private ArrayList<Student> students;
private ArrayList<Module> modules;
private Module moduleLink;
public Model(){
students = new ArrayList<Student>();
modules = new ArrayList<Module>();
}
public void runTests() throws FileNotFoundException{
System.out.println("Beginning program, the ArrayList of students will now be loaded");
loadStudents("studentlist.txt");
System.out.println("Load attempted, will now print off the list");
printStudents();
System.out.println("The module list will now be loaded and printed");
loadModules("moduleslist.txt");
printModules();
System.out.println("Modules printed, ArrayList assosciation will commence");
}
public void printStudents(){
for(Student s: students){
System.out.println(s.toString());
}
}
public void printModules(){
for(Module m: modules){
System.out.println(m.toString());
}
}
public void loadStudents(String fileName) throws FileNotFoundException{
Scanner infile =new Scanner(new InputStreamReader
(new FileInputStream(fileName)));
int num=infile.nextInt();infile.nextLine();
for (int i=0;i<num;i++) {
String u=infile.nextLine();
String s=infile.nextLine();
String n=infile.nextLine();
String c=infile.nextLine();
Student st = new Student(u,s,n,c);
students.add(st);
}
infile.close();
}
public void loadModules(String fileName) throws FileNotFoundException{
Scanner infile =new Scanner(new InputStreamReader
(new FileInputStream(fileName)));
int numModules = infile.nextInt();
infile.nextLine();
for (int i=0;i<numModules;i++){
String code = infile.nextLine();
int numStudents = infile.nextInt();
infile.nextLine();
ArrayList<Student> enrolledStudents = new ArrayList<Student>(numStudents);
for (int a=0;a<numStudents;a++){
String uid = infile.nextLine();
Student st = new Student(uid);
enrolledStudents.add(st);
}
Module m = new Module(code,enrolledStudents );
modules.add(m);
}
infile.close();
}
}
Any help would be very appreciated, thanks.
If you are looking for Student details, probably you should re-design your classes.
Student should be enrolled to a module. Hence, Student should have Module. And use a Map to retrieve students based on the id.
class Student {
String id;
List<Module> modules = new ArrayList<Module>();
}
loadStudents() would remain same except that you have to populate a Map of student id to Student objects you create in the loop.
loadModules() would then pick the student based on student id from the map and update the modules.
This would be the case where you need data based on Student.
Related
I dont understand why i am not able to read from the file.I am always getting null with Readline() method of BufferedReader .
TestStudent class should be able to perform the following functions:
Create an ArrayList object of Student objects called studentList, using the student data stored in a text file named students.txt (you should create this file such that it stores the student name and ID of several students initially – one line per student)
Allow the user to add as many new Student objects as the user requests to the ArrayList ensuring that each student has a unique student ID
When the user has finished adding new students to the list, the program will override the students.txt file such that it includes the data relating to the new students as well as the original ones
Ability to display a full list of students as well as just the existing student IDs when necessary
Here's what i have done till now.
import java.util.*;
import java.io.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.ArrayList;
public class TestStudent {
public static void main(String[] args) throws IOException {
File f=new File("C:\\Users\\user1\\Desktop\\Students.txt");
BufferedWriter bw = new BufferedWriter(new FileWriter(f));
// FileReader reads text files in the default encoding.
FileReader fileReader =
new FileReader(f);
// Always wrap FileReader in BufferedReader.
BufferedReader bufferedReader =
new BufferedReader(fileReader);
//File f=new File("Student.txt");
Scanner sc=new Scanner(System.in);
Scanner scan = new Scanner(f);
ArrayList<Student> studentList = new ArrayList<>();
String cont;
do {
System.out.println("Enter Student Name:");
String name=sc.next();
System.out.println("Enter Student ID:");
String id=sc.next();
bw.write(name);
bw.write("\t"+id);
bw.newLine();
System.out.println("Continue Adding?");
cont=sc.next();
}
while(cont.equalsIgnoreCase("y"));
while(bufferedReader.readLine() != null){
String line = bufferedReader.readLine();
String[] record = line.split("\t");
Student myStudent =new Student(record[0],record[1]);
studentList.add(myStudent);
}
for(Student st:studentList)
System.out.println(st.Name+" "+st.Id);
bw.close();
scan.close();
sc.close();
}
}
class Student{
String Name, Id;
with default value red
Student(String string, String string0) {
System.out.println("s");
}
//Following are Mutators methos
public String getName() {
return this.Name;
}
public String getId() {
return this.Id;
}
//Following are accessor Methods
public void setName(String s){
this.Name=s;
}
public void setID(String ID) {
this.Id = ID;
}
public String toString() {
return "Student name is "+getName()+" Student Id is "+getId();
}
public boolean isValidID() {
if(getId().length()!=6)
return false;
else{
for(int i=0;i<getId().length();i++){
if(Id.charAt(i)>'9'||Id.charAt(i)<'0')
return false;
}
return true;
}
}
public boolean IDExists(Student other) {
if(other.getId().equals(this.getId()))
return true;
else
return false;
}
}
The problem is here:
while(bufferedReader.readLine() != null){
String line = bufferedReader.readLine();
...
}
The first call to readLine() reads the line, but does not assign it - its lost. The next call to readLine() reads the next line.
It should be:
String line = null;
while ((line = bufferedReader.readLine()) != null){
....
}
This reads the next line, assign it to line, and then compares to null.
Then, your student constructor is broken:
Student(String string, String string0) {
System.out.println("s");
}
You never assign string and string0 to anything, and Id and Name are not assigned and always null.
Your code furthermore does not compile:
String Name, Id;
with default value red
This is a syntax error.
Read about How to create a Minimal, Complete, and Verifiable example to ensure your code is working and your question focused on one problem at a time. Most of your problems would be gone simply by making sure you test every part of your program separately and make sure it actually compiles.
you forgot to assign studentID and studentName for new Object in constructor
Student(String string, String string0) {
System.out.println("s");
id = string;
name = string0;
}
and because you write and read the same file so you must close fileWriter before reading
do {
// your code
}
while(cont.equalsIgnoreCase("y"));
// close buffer writer before reading
bw.close()
String line;
while((line = bufferedReader.readLine()) != null){
String[] record = line.split("\t");
Student myStudent =new Student(record[0],record[1]);
studentList.add(myStudent);
}
I want to get information from the user like last name, first name, and id number for example Smith, John 12345 and continue looping until the user enters "exit". Whenever I enter two inputs the first one gets wiped out and the second one is stored. Maybe I should be using a different approach then what I have...
InputStreamReader reader = new InputStreamReader(System.in);
BufferedReader input = new BufferedReader(reader);
String inputValues;
String person;
String lastname = "";
String firstname = "";
String id = "";
while(true){
inputValues = input.readLine();
person = inputValues.split("\\s+");
if(inputValues.equals("exit"){
break;
}
else {
lastname = person[0];
firstname = person[1];
id = person[2];
}
}
I know my program is wrong but this is what I have thus far. I do not know how to store multiple people to eventually print out their names and id at the end of this.
I hope I understand your problem correct: your problem is that you overwrite your old entries? To prevent that you have to use some kind of array or list.
import java.util.*;
import java.lang.*;
import java.io.*;
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
InputStreamReader reader = new InputStreamReader(System.in);
BufferedReader input = new BufferedReader(reader);
String inputValues;
String[] person;
List<String> lastname = new ArrayList<String>();
List<String> firstname = new ArrayList<String>();
List<String> id = new ArrayList<String>();
while(true){
inputValues = input.readLine();
person = inputValues.split("\\s+");
if(inputValues.equals("exit")){
break;
}else{
lastname.add(person[0]);
firstname.add(person[1]);
id.add(person[2]);
}
}
for(int i=0; i<lastname.size(); i++)
System.out.println(firstname.get(i) +" "+ lastname.get(i) +" ("+ id.get(i) +")");
}
}
See here: https://ideone.com/l1TnF8
Just as kon has noted you need an array of strings for person, what is happening is that each time you input a new value the new one only replaces the old one since person is only a string occupying just one memory space.
I'm fairly new to programming and I recently wrote something to utilize a scanner class to fill an object array from a text file. Essentially, I can re-write this text file or add new info and won't have to change the code. I suppose my question is this: is there an easier/more preferred method to doing this? I'm trying to learn the coding nuances.
import java.io.*;
import java.util.*;
public class ImportTest {
public static void main(String[] args) throws IOException
{
Scanner s = null;
Scanner k = null;
ArrayList myList = new ArrayList<String>();
ArrayList myList2 = new ArrayList<String>();
ArrayList myList3 = new ArrayList<Student>();
try
{
s = new Scanner(new BufferedReader(new FileReader("testMe.txt")));
while (s.hasNext())
{
myList.add(s.nextLine());
}
}
finally
{
if (s != null)
{
s.close();
}
}
System.out.println("My List 1:");
for(int i=0; i<myList.size(); i++)
{
System.out.println(i+". "+myList.get(i));
}
for(int x=0; x<myList.size(); x++)
{
try
{
k = new Scanner(myList.get(x).toString());
while (k.hasNext())
{
myList2.add(k.next());
}
}
finally
{
if (k != null)
{
k.close();
}
}
String name;
int age;
double money;
name=myList2.get(0).toString();
age=Integer.parseInt(myList2.get(1).toString());
money=Double.parseDouble(myList2.get(2).toString());
Student myStudent=new Student(name, age, money);
myList3.add(myStudent);
myList2.clear();
}
System.out.println("Test of list object: ");
for(int i=0; i<myList3.size(); i++)
{
System.out.println(i+". "+myList3.get(i).toString());
}
}
}
I would read the file line by line and parse every line directly. This way you do not need 3 lists, 2 scanners and multiple iterations:
String line = "";
BufferedReader br = new BufferedReader(new FileReader("test.txt"));
ArrayList<Student> students = new ArrayList<Student>();
while( (line = br.readLine()) != null)
{
String[] tmp = line.split("\\s+"); //split line by spaces
//this needs bounds & error checking etc.
students.add(new Student(tmp[0], Integer.parseInt(tmp[1]), Double.parseDouble(tmp[2])));
}
In Java 7 you can use the new file functions to read all lines at once:
List<String> allLines = Files.readAllLines("test.txt", Charset.defaultCharset());
Do not forget to close the reader or use try-with-resources (since java 1.7)
Correct me if I am wrong, testMe.txt file contains Student information which are name, age, money, and you want read those values.
Best way to do it is you should serialize your Student objects into the the testMe.txt with the help of ObjectOutputStream. As well you can read those value using ObjectInputStream, so in this way you can able to get Student objects itself(no need to hnadle String).
In case you do want to serialize the data into file, you should store the data in some predefined format like as comma(,) or semi-colon(;) seperated.
For Example -
emp1, 24, 20000
emp emp2, 25, 24000
emp3, 26, 26000
In this case while reading the string you can split it with seperation character and get the actual information.
Code snippet:
List<Student> students = new ArrayList<Student>();
...
try(scanner = new Scanner(new BufferedReader(new FileReader("testMe.txt")))){
while (scanner.hasNext()){
String data[] = scanner.nextLine().split(",");
Student student = new Student(data[0],data[1],data[2]);
students.add(student);
}
}
Try-with-resource will automatically handle the resouce, you dont need to explicitly close it. This features available in java since 1.7.
i am doing a self project to help me understand more about java.but i am stuck at this question.
I have a following txt file :
Name Hobby
Susy eat fish
Anna gardening
Billy bowling with friends
What is the best way to read all the line and put it in arraylist(name,hobby). but the tricky part is the
eat fish or bowling with friends
has white spaces and it must be put under one array and obviously i cannot hardcode it.
here is my current code
public void openFile(){
try{
x = new Scanner(new File("D://practice.txt"));
}catch (Exception e){
System.out.println("File could not be found");
}
}
public void readFile(){
while (x.hasNextLine()){
x.nextLine();
if (x.hasNext()){
listL.add(x.next());
} else {
listL.add("");
}
if (x.hasNext()){
listR.add(x.next());
} else {
listR.add("");
}
}
}
thanks in advance...
note = 1.hobby and name are separated by spaces
2.names will only have one word only
Instead of doing scanner.next(), you may want to do something like this:
Scanner scan = new Scanner(new File("D://practice.txt"));
ArrayList<String> names = new ArrayList<String>();
ArrayList<String> hobbies = new ArrayList<String>();
while(scan.hasNext()){
String curLine = scan.nextLine();
int indexOfHobby = curLine.indexOf(' ');
names.add(curLine.substring(0, indexOfHobby).trim());
hobbies.add(curLine.substring(indexOfHobby).trim());
}
One problem with this is that there is no relationship between the two ArrayLists, so you have to be sure to mind your indices as you iterate through. One way to fix this would be to add a Person class so that you can have name and hobby as attributes of Person, then have an ArrayList of Persons. That might look like this:
Class Person {
String name;
String hobby;
public Person(String name, String hobby){
this.name = name;
this.hobby= hobby;
}
// more methods here
}
Then, in your main class, you'd do this:
Scanner scan = new Scanner(new File("D://practice.txt"));
ArrayList<Person> people= new ArrayList<Person>();
while(scan.hasNext()){
String curLine = scan.nextLine();
int indexOfHobby = curLine.indexOf(' ');
people.add(new Person(curLine.substring(0, indexOfHobby).trim(), curLine.substring(indexOfHobby).trim() ));
}
Also consider using a Map<String,String> to store people with their hobby together instead of keeping two different structures:
Scanner scan = new Scanner(new File("D://practice.txt"));
Map<String,String> namesAndHobbies = new HashMap<String,String>();
while(scan.hasNext()){
String line = scan.nextLine();
int idx = line.indexOf(' ');
String name = line.substring(0, idx).trim();
String hobby = line.substring(idx).trim();
namesAndHobbies.put(name, hobby);
}
This will allow you to access people by name, so you can find out the hobby of a person by name.
Use namesAndHobbies.keySet() to get a collection of all names and namesAndHobbies.values() to get a collection of all hobbies.
So after completing the last assignment I was given, I was instructed to take that code and change it from command line arguments to reading in data from a file. That all works out well, except for the part where I'm supposed to have an interface for a function that calls in the data from the file, then does the same things as before.
Right now, the object array in my driver class is SUPPOSED to be assigned the values taken in by the DAO class. The DAO class is based off the interface. The driver class is screaming at me that the object I have created has to be assigned from a static function in the DAO class, but that method can't be static...
What did I miss this time?..
Interface:
public interface ScanTextFile {
public Object[] readTextData() throws FileNotFoundException;
}
DAO Class:
public class StudentDAO implements ScanTextFile {
public Object[] readTextData() throws FileNotFoundException {
Student[] studentRecord = new Student[3];
String dataFileName = "data.txt";
int numberOfRows = 0;
File dataFile = new File(dataFileName);
Scanner scan = new Scanner(dataFile);
int i = 0;
String delim = "\\|";
// checks number of rows in data file, making sure there are 3 total
for(i = 0; scan.hasNextLine(); i++){
numberOfRows++;
}
if(numberOfRows < 3){
System.err.format((numberOfRows) + " argument(s) - expected 3");
System.exit(0);
} else if(numberOfRows > 3){
System.err.format((numberOfRows) + " arguments - expected 3");
System.exit(0);
}
for(i = 0; i < numberOfRows; i++){
if(scan.hasNextLine()){
String temp = scan.nextLine();
String[] tempData = new String[4];
Student tempStudent = null;
for(i = 0; i < tempData.length ; i++){
tempData = temp.split(delim);
}
System.out.println("DEBUG *** Finished extracting data, creating object...");
System.out.println("DEBUG Student Data = [�" + temp + "]");
GregorianCalendar date = new GregorianCalendar();
try {
date = DateUtil.convertFromDMY(tempData[3]);
} catch (ParseException e1) {
e1.printStackTrace();
}
tempStudent = new Student(tempData[0], tempData[1], tempData[2], date);
studentRecord[i] = tempStudent;
}
}
return studentRecord;
}
}
Driver Class:
public class Lab3 {
public void main(String[] args) throws ParseException, FileNotFoundException{
Student[] allData = new Student[3];
allData = (Student[]) StudentDAO.readTextData();
System.out.println("");
System.out.println("DEBUG *** Student Objects created, displaying all Students...\n");
for(Student s : allData){
Print.print(s);
}
}
}
edit
Thanks for pointing out that error, thanks everyone, but now I'm getting
Exception in thread "main" java.lang.NoSuchMethodError: main
Is that because StudentDAO has no main?
another edit
#mprabhat thanks for pointing out a really stupid error, still don't know how I didn't see that ><
Now I have an issue when the scanner attempts to read the data in from the file.
1 - says data file can't be found, even though it's in my src folder.
2 - error on the scanner line as well, should I not be using a scanner on a file? should I be going with ... DataInputStream?
Your method readTextData is not static but you are accessing it like a static method by using class name StudentDAO
StudentDAO.readTextData();
Instead create an object StudentDAO and then call readTextData
Student[] allData = new Student[3];
StudentDAO studentDAO = new StudentDAO();
allData = (Student[]) studentDAO.readTextData();
Issue in your Lab3 is that you dont have correct signature of your main method.
public static void main(String[] args) is the correct signature, your signature is missing static, hence you are getting java.lang.NoSuchMethodError: main
In the class Lab3, create and instance of StudentDAO and then read the text as below:
StudentDAO dao = new StudentDAO();
allData = (Student[]) dao.readTextData();
You have 2 things basically:
readTextData() is not static, hence you can't access it in the same manner you are doing. You will need to create an object and then call that method.
You are creating an array of 3 elements you are then discarding and populating with some new data.
So basically you need to replace this:
Student[] allData = new Student[3];
allData = (Student[]) StudentDAO.readTextData();
with this:
StudentDAO sDao = new StudentDAO();
Student[] students = (Student[])sDao.readTextData();
For completeness sake, if you do as follows you should also get rid of the error, but I would recommend you stick with the approach I have just listed above:
In your interface class replace this: public Object[] readTextData() throws FileNotFoundException; with this: public static Object[] readTextData() throws FileNotFoundException;. This will make your readTextData method static. Replacing the method signature in your DAO (with public static Object[] readTextData() throws FileNotFoundException;) class should then remove the error you are facing.