I'm writing a program that reads from a file. Each line in the file contains information about a student.Each student is represented by an object from the class "Student". The class Student has a method getName that returns the student's name.The method that goes through the file returns and ArrayList containing student objects. My problem is that every time I use a for loop to access the ArrayList and get the name of each student, what I get is the name of the last student in the list. The method that go through the file is called "FileAnalyzer" Below is my code.
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class StudentStats {
public static void main(String[] args) {
List<Student> example = null;
example = FileAnalyzer("C:\\Users\\achraf\\Desktop\\ach.csv");
for ( int i = 0; i < example.size(); i++)
{
System.out.println(example.get(i).getName());
}
}
public static List<Student> FileAnalyzer(String path) //path is the path to the file
{
BufferedReader br = null;
List<Student> info = new ArrayList<Student>();
String line = "";
try {
br = new BufferedReader (new FileReader(path));
while ((line = br.readLine()) != null)
{
//We create an object "Student" and add it to the list
info.add(new Student(line));
}
}
catch (FileNotFoundException e) {
System.out.println("Aucun fichier trouvé");
} catch (IOException e) {
e.printStackTrace();
}
finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return info;
}
In case you need it, here's the code for the class student
// This class create objects for each student
public class Student {
private static String Name ="";
private static String Sex = "";
private static String Grade = "";
//constructor
public Student(String infos)
{
String [] etudiant = infos.split(",");
Name = etudiant[0];
Sex = etudiant[1];
Grade = etudiant[2];
}
// Getter functions
public String getName()
{
return Name;
}
public String getSex()
{
return Sex;
}
public String getGrade()
{
return Grade;
}
}
Below is the content of a typical file that the programs reads.
lovett,M,12
Achos,F,23
Loba,M,24
THE REAL problem is that after running my code to get the names, I get the name "Loba" three times instead of getting all the names.
Here is the problem in your Student class:
private static String Name ="";
private static String Sex = "";
private static String Grade = "";
You need to remove the static from the member variables otherwise all the objects will share the same attributes and hence you see only the last values written in those variables always.
Learn more about instance and class variables here: http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html
Your member variables are declared static in the Student class. That means that they exist as one copy throughout your program, not as one copy per instance which is what you want. Every time you're creating a new student, you're setting the name, sex and grade to something new, but these values are not associated with any particular student. All students share these attributes, and they are being overwritten in your file reading loop, so whatever is the last name in your file will be the name of the static variables.
Related
This question already has answers here:
What is the difference between a member variable and a local variable?
(7 answers)
Closed 4 years ago.
I've already looked at all of the other stackoverflow questions on accessing an instance of an object from the main method and nothing I've tried has worked, I still continue to get the following error message
java.59: error: cannot find symbol
System.out.println(student2.getStudentId());
here is my main method trimmed down:
import java.util.Scanner;
import java.io.*;
import java.util.Arrays;
public class Testing {
public static void main (String [] args) throws IOException {
final String INPUT_FILE = "c:\\Users\\XXXXXX\\Documents\\Input01.txt";
Scanner br = new Scanner(new File(INPUT_FILE));
// Test 2 - Test first and second line of information from input file
String[] strArray;
while (br.hasNext()) {
strArray = br.nextLine().split(",");
if(strArray[0].equals("STUDENT")) {
processStudentData(strArray);
System.out.println(student2.getStudentId());
}
else
if(strArray[0].equals("GRADE ITEM")) {
processGradeItemData(strArray);
}
}
} //end main
// ***************************************************************
// Uses string array from input file to create new student object
public static void processStudentData(String[] a) {
System.out.println("Running Test 2a:");
if (a[1].equals("ADD")) {
Student student2 = new Student(a[2], a[3], a[4], a[5]);
}
} // End processStudentData
} //end Testing
here is my Student class trimmed down:
public class Student {
private String studentId; // Unique ID for each Student
private String studentFirstName; // Student's legal first name
private String studentLastName; // Student's legal last name
private String studentEmail; // Student's school email address
//************************************************************************
Student() {
} // end Student
//************************************************************************
public Student(String studentId, String studentFirstName, String studentLastName,
String studentEmail) {
if (studentId.equals("")) {
throw new IllegalArgumentException("Student ID cannot be blank.");
}
if (studentFirstName.equals("")) {
throw new IllegalArgumentException("Student first name cannot be blank.");
}
if (studentLastName.equals("")) {
throw new IllegalArgumentException("Student last name cannot be blank.");
}
if (studentEmail.equals("")) {
throw new IllegalArgumentException("Student email cannot be blank.");
}
if (!studentEmail.contains("#")) {
throw new IllegalArgumentException("Student email must have '#'.");
}
this.studentId = studentId;
this.studentFirstName = studentFirstName;
this.studentLastName = studentLastName;
this.studentEmail = studentEmail;
} // end Student
//************************************************************************
public String getStudentId() {
return studentId;
} // end getStudentId
I need to be able to print out the student information using my get methods from the main method yet still instantiate the student2 object through the processStudentData method. I do not want to have to change my get method to static as there will be multiple instances.
Any help would be greatly appreciated.
UPDATE: I've added in a return to the processStudentData method and am still recieving the same error as before (main method has not changed, processStudentData method updated below):
public static Student processStudentData(String[] a){
System.out.println("Running Test 2a:");
if (a[1].equals("ADD")) {
Student student2 = new Student(a[2], a[3], a[4], a[5]);
return student2;
}
return null;
}
Since student2 is defined as a local variable within the if statement of the processStudentData, it can only be used within that context (to which it is defined)
// Uses string array from input file to create new student object
public static void processStudentData(String[] a) {
System.out.println("Running Test 2a:");
if (a[1].equals("ADD")) {
Student student2 = new Student(a[2], a[3], a[4], a[5]);
}
} // End processStudentData
"A" solution would be to return the result to the caller...
// Uses string array from input file to create new student object
public static Student processStudentData(String[] a) {
System.out.println("Running Test 2a:");
if (a[1].equals("ADD")) {
return new Student(a[2], a[3], a[4], a[5]);
}
return null;
} // End processStudentData
Then you could use it something like...
Student student = processStudentData(strArray);
if (student != null) {
System.out.println(student.getStudentId());
}
You might want to take a closer look at:
Language Basics/Variables
Returning a Value from a Method
for more details
Try to do something like:
public static Student processStudentData(String[] a) {
System.out.println("Running Test 2a:");
if (a[1].equals("ADD")) {
Student student2 = new Student(a[2], a[3], a[4], a[5]);
return student2;
}
return null;
}
and don't forget to handle the NullPointerException.
I am trying to create a program that will allow a teacher to grab students from a roster, then throw them into random groups. I plan on creating an arraylist from the text file that has a bunch of student names on it. I need help pulling the students names from the file and then inserting their names into an array list.
Here is where the array would come in handy (other places too but program is not complete):
try {
System.out.println("Please enter the name of the student that you would like to add to the file as \"Last name, First name\"");
PrintWriter outputStream = new PrintWriter(new FileOutputStream(fileName, true));
Scanner sc = new Scanner(System.in);
String s = sc.next();
outputStream.println(s);
sc.close();
outputStream.close();
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
I also need to involve a couple of classes in this program so I created this class, my idea with this is one is that I can create an open variable for the students that are on file.
public class Name {
private String studentName;
public Name() {
}
public Name(String studentName) {
this.studentName = studentName;
}
public String getstudentName() {
return studentName;
}
public void setstudentName(String studentName) {
this.studentName = studentName;
}
}
And here is the text file with some names, the challening part for me is that there is a comma separating the names (maybe I should remove that?) :
Ospina, Bryan
Patel, Krupa
Preite, Nicholas
Quigley, Kevin
Rubet, Aaron
Said, Abanoub
Sidler, Allen
Thiberge, Daniel
Thota, Raajith
Tripathi, Rashi
Tsang, Johnny
Velovic, Joseph
Victor, Samuel
Whitted-Mckoy, Eric
Wu, Michelle
Edit: Condensed the code
Using a Stream, which you will not be able to use for your homework...
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Stream;
import java.util.stream.Collectors;
public class Demo {
public static void main(String[] args) throws IOException {
final String filename = "whatever";
List<Name> list =
Files.lines(Paths.get(filename)) // Strings, lines in the file
.map(line -> line.split(",")) // String[], split by ,
.map(split -> split[1] + split[0]) // String, joined again
.map(Name::new) // Name, make a Name object from String
.collect(Collectors.toList()); // collect into a List<Name
}
public static class Name {
private final String studentName;
public Name(String studentName) {
this.studentName = studentName;
}
public String getstudentName() {
return studentName;
}
}
}
Please check:
Manipulate data from a file and then store it into an array
I had the exact same.
Here is alternative way how to accomplish your task:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Scan {
public static void main(String[] args) {
String fileName = "text.txt";
List<Name> names = new ArrayList<>();
try (Scanner scan = new Scanner(new File(fileName))) {
while (scan.hasNext())
names.add(new Name(scan.nextLine().replace(",", "")));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
System.out.println(names);
}
public static class Name {
private final String studentName;
public Name(String studentName) {
this.studentName = studentName;
}
public String getstudentName() {
return studentName;
}
#Override
public String toString() {
return studentName;
}
}
}
By using class Scanner you can read a file as follow: Scanner scan = new Scanner(new File(fileName)). Read file line by line: scan.nextLine() until end of file: while (scan.hasNext()). Create new instance of Name: new Name(scan.nextLine().replace(",", "")) and add it into list: names.add(...). To remove , used replace(",", "") method of String class.
How do you create a string array list from a text file in java?
You need to read until the End Of File, I am showing one of the approaches using the BufferedReader until the end of the file.
BufferedReader br = new BufferedReader(new FileReader("pathToYourFile"));
String input = null;
String [] splittedInput = null;
String fullName = null;
List<Name> names = new ArrayList<>(); // Maintaining all the names
while((input = br.readLine()) != null) { // Until the End
splittedInput = input.split(",");
fullName = splittedInput[1] + splittedInput[0]; // Since file stoes lastname,firstname
names.add(new Name(fullName));
}
//Now names list contains all Name Object
I am working on a project ( I had a problem yesterday and so many people helped me!) so I decided to ask for help again.
My code has 3 classes. ProjectMain,Students,Classroom. I created an array of Classroom objects. Right now I have 3 Classroom objects. But I have to assign student objects to these Classroom objects. For example : classarray[0] is an object from Classroom class and studentobject.get(0) , studentobject.get(1) ... will be students objects inside classarray[0] object. But I have failed on this while coding. Here are my classes :
public class Classroom
{
private String classname;
private String word[] = null;
protected ArrayList<Students> studentobject = new ArrayList<Students>(10);
public String[] getWord()
{
return word;
}
public void setWord(String[] word)
{
this.word = word;
}
public ArrayList<Students> getStudentobject()
{
return studentobject;
}
public void setStudentobject(ArrayList<Students> studentobject)
{
this.studentobject = studentobject;
}
public String getClassname()
{
return classname;
}
public void setClassname(String classname)
{
this.classname = classname;
}
public void classroomreader(String filename)
{
// This method gets the name of Classroom
File text = new File("C:/Users/Lab/Desktop/classlists/" + filename
+ ".txt");
Scanner scan;
try
{
scan = new Scanner(text);
String line = scan.nextLine();
word = line.split("\t");
line = scan.nextLine();
word = line.split("\t");
} catch (FileNotFoundException e1)
{
e1.printStackTrace();
}
}
}
This is my student class :
public class Students extends Classroom
{
private String name,id;
private int age;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
And my main class :
public class ProjectMain
{
public static void main(String[] args)
{
Classroom[] classarray = new Classroom[3];
//I got 3 Classroom objects here
classarray[0]=new Classroom();
classarray[1]=new Classroom();
classarray[2]=new Classroom();
classarray[0].classroomreader("class1");
classarray[0].studentobject.get(0).setName(classarray[0].getWord()[1]);
//The problem is in here. When my code comes to the line above,
// at java.util.ArrayList.rangeCheck(Unknown Source) error comes out.
// I tried to get first object in studentobject Arraylist, and tried to set it's name
// to the variable which my text reader reads.
How can I write what I have in my mind?
Your classroomreader method reads the file but don't do much of it... maybe you want to create some instance of Students within it.
scan = new Scanner(text);
String line = scan.nextLine();
word = line.split("\t"); // won't be used
line = scan.nextLine();
word = line.split("\t"); // erased here
There you only have the last line (split) of the file in word attribute.
When creating Classroom instance studentobject list is created empty and it stays that way so you can't access first (or any) object in it.
To populate your list you may add to Classroom method like this:
public void addStudent(Student s)
{
studentobject.add(s);
}
classroom contains the following field declaration
String word[] = null;
the main class, incl the classroomreader does not set a value to this field. Yet you are going to invoke
classarray[0].getWord()[1]
which then must fail.
tip: don't use expressions like this, which can be found in your main class (at least not in early stages of development, or learning)
classarray[0].studentobject.get(0).setName(classarray[0].getWord()[1]);
resolve into variables and several steps. Compilers are smart enough to produce the same code if the context is not disturbed, ie the long expression is resolved into a single block.
Never forget that the purpose of programming languages is to make programs readable for humans. :) Code with abbreviations or "tricks" simply shows some philodoxical attitude (imho)
I am new at coding. I was doing a project but I was stuck. My code reads a sentence from a text file. It seperates the sentence and gets the second word and records it in an array. I need to use this word in another place but I couldn't do it.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Classroom {
private String classname;
public String getClassname() {
return classname;
}
public void setClassname(String classname) {
this.classname = classname;
}
public void classroomreader(String filename) {
// This method gets the name for Classroom
File text = new File("C:/classlists/" + filename + ".txt");
Scanner scan;
try {
scan = new Scanner(text);
String line = scan.nextLine();
String classroomarray[] = line.split("\t");
// ** right now classroomarray[1] has the word which I want.**
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
}
}
Here is my main class:
public class ProjectMain {
public static void main(String[] args) {
// I created an array with 3 Classroom object inside it.
Classroom[] classarray = new Classroom[3];
//I hope I did this correct.
// I used classroomreader method on my first object.
classarray[0].classroomreader("class1");
// Now I need to use the word in classroomarray[1].
classarray[0].setClassname(????)
}
}
I tried: classarray[0].setClassname(classroomarray[1]); but it gave an error. How can I set the name for my first object?
i'm making just few changes in your code.. try this....definitely this'll work
class Classroom {
private String classname;
String classroomarray[]=null;//declare classroomarray[] here
public String getClassname() {
return classname;
}
public void setClassname(String classname) {
this.classname = classname;
}
public void classroomreader(String filename) {
File text = new File("C:/classlists/" + filename + ".txt");
Scanner scan;
try {
scan = new Scanner(text);
String line = scan.nextLine();
classroomarray = line.split("\t");
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
}
}
class ProjectMain {
public static void main(String[] args) {
Classroom[] classarray = new Classroom[3];
//here you need to initialize all elements of the array
classarray[0]=new Classroom();
classarray[1]=new Classroom();
classarray[2]=new Classroom();
classarray[0].classroomreader("class1");
classarray[0].setClassname(classarray[0].classroomarray[1]);
System.out.println(classarray[0].getClassname());// here you'll surely get the the desired results
}
}
Its a little hard for me to understand what your code in the top is doing.. that being said I believe if you have a private variable in your top class and then have an accessor method like
public String getPrivateFieldValue()
{
return somePrivateFieldName;
}
Then you can can set the private variable in your main class when you find the value for it. In your main class you can then say:
Object.getPrivateFieldValue() to get that value
or in your situation:
classarray[0].setClassname(classroomreader.getPrivateFieldValue())
I think your problem lies with the concept of scope. Whenever you create a variable, like classroomarray, java registers that the name of that variable then represents the value you assign to it (in simple terms).
Now what Scope means is that not all variables can be accessed from every place. Classroomarray is created inside classroomReader(), but does not get out of that function once it completes. In a way "lives" inside that function, and that's why you can't use it in the main() method.
If you want to use classroomarray inside the main() method, you'll need to transport it there through some means. There are multiple ways of doing this:
Create a field in ClassRoom, like public String[] classroomarray
Return the classroom array you read from the file from the classroomreader() function. Returning a value means that you're "sending back" a value to whatever code called the function in the first place. For example, add(a, b) would return the sum of a and b. You do this by changing:
public void classroomreader(String filename)
To:
public String[] classroomreader(String filename)
And change:
String classroomarray[] = line.split("\t");
To:
return line.split("\t");
Then, in the main() method, you can use:
String[] classroomFile = classarray[0].classroomreader("class1");
And use the contents as you please.
This is an Example,Hope you don't mind hard interpretation. Please add return to your method like this.
public String[] demo() //Added ()
{
String[] xs = new String[] {"a","b","c","d"}; //added []
String[] ret = new String[4];
ret[0]=xs[0];
ret[1]=xs[1];
ret[2]=xs[2];
ret[3]=xs[3];
return ret;
}
So your new code will be like this
public String[] classroomreader(String filename) {
// This method gets the name for Classroom
File text = new File("C:/classlists/" + filename + ".txt");
String[] classroomarray;
Scanner scan;
try {
scan = new Scanner(text);
String line = scan.nextLine();
classroomarray = new String[] {line.split("\t")};//Change this
// ** right now classroomarray[1] has the word which I want.**
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
return classroomarray;
}
In Main method change this:
String [] strArr = demo();//Calling method which returns value clasroomarray
for ( int i = 0; i < strArr.length; i++) {
System.out.println(strArr[3]);//Printing whatever index you want
//Set Values here like this
Classroom classroom=new Classroom();//Initialize your object class
classroom.set(strArr[3]); //Set value
Hi i suggest you declare
classroomarray[]
as a member variable. Then generate getters and setters.
Later you can do what you want by setting
classarray[0].setClassname(classarray[0].getClassroomarray[1]);
I'm trying to help you on the way you want it to be done, but i don't understand why you wanna it to be done like that.
Edit : Here is the code i'm talking about in the comments below
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Classroom {
private String classname;
public String getClassname() {
return classname;
}
public void setClassname(String classname) {
this.classname = classname;
}
public void classroomreader(String filename) {
// This method gets the name for Classroom
File text = new File("C:/classlists/" + filename + ".txt");
Scanner scan;
try {
scan = new Scanner(text);
String line = scan.nextLine();
String classroomarray[] = line.split("\t");
// ** right now classroomarray[1] has the word which I want.**
this.classname = classroomarray[1];
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
}
}
And finally your main method should look like
public class ProjectMain {
public static void main(String[] args) {
// I created an array with 3 Classroom object inside it.
Classroom[] classarray = new Classroom[3];
classarray[0]=new Classroom();
//I hope I did this correct.
// I used classroomreader method on my first object.
classarray[0].classroomreader("class1");
// Now classname is already set
System.out.println(classarray[0].getClassname());
}
}
I want this program to ask the user for input, and create a class instance with a name equal to the input of the user. Then, the createMember class will create a text file, where all the data of the user will be stored. How do I go about doing it?
Here's the main method:
public static void main(String[] args) {
String input = keyboard.nextLine();
input = new createMember(); // Error. can't do that for some reason?
}
}
Here's the createMember class
public class createMember {
public void setMembership() {
Scanner keyboard = new Scanner(System.in);
out.println("Username: ");
String input = keyboard.nextLine();
try {
//Creates a text file with the same name as the username where data is stored.
Formatter x = new Formatter(input);
} catch (Exception e) {
out.println("Could not create username");
}
}
//Methods for the user
Guys... I know I can simply create an instance like this:
createMember member = new createMember();
What I actually want to do is HAVE THE USER do that on his own, so the program is flexible and usable for many people. So, based on the input, there will be a separate folder that stores the data for each user.
Looks like you need a non-default Constructor: (Constructors CANNOT return any value, not even void, as the instance is what is actually returned.
String input = keyboard.nextLine();
Member m = new Member(input);
public class Member {
private String name;
public Member(String name) {
this.name = name;
}
public void setMembership() {
try {
//Creates a text file with the same name as the username where data is stored.
Formatter x = new Formatter(name);
} catch (Exception e) {
out.println("Could not create username");
}
}
}
You need a constructor
public class CreateMember {
private String input;
public CreateMember(String input){
this.input = input;
}
public String getInput(){
return input;
}
}
To access the input use CreateMember.getInput()
public static void main(String[] args){
String input = scanner.nextLine();
CreateMember member = new CreateMember(input);
System.out.println(member.getInput());
}