Cannot add new object to a set, values come from a file - java

I am trying to create a public instance method that takes no arguments and returns no values. It is required to get an input from a user to select a file, this part I have no issues with. The method needs to make use of the BufferReader and Scanner Objects. So that it can read the file selected. For each line that is read, a new object should be created and its instance variables set using the values found in the file.
That object that is created should then be added to a list. This is where I am having issues, it won't let me add the new object to the list. Below is my code:
public void readInEntrants()
{
String pathname = OUFileChooser.getFilename();
File aFile = new File(pathname);
Scanner bufferedScanner = null;
Set<Entrant> entrantSet = new HashSet<>();
try
{
String currentEntrantLine;
Scanner lineScanner;
bufferedScanner = new Scanner(new BufferedReader(new FileReader(aFile)));
while (bufferedScanner.hasNextLine())
{
currentEntrantLine = bufferedScanner.nextLine();
lineScanner = new Scanner(currentEntrantLine);
lineScanner.useDelimiter(" ");
currentEntrantLine = lineScanner.next();
entrantSet.add(new Entrant(currentEntrantLine)); // <----- Here is where I am having trouble. It won't let me add the new object to the class Entrant
}
}
catch (Exception anException)
{
System.out.println("Error: " + anException);
}
finally
{
try
{
bufferedScanner.close();
}
catch (Exception anException)
{
System.out.println("Error: " + anException);
}
}
return entrantSet;
}
I'm not sure what to do. Could anyone see what I am doing wrong?
Sorry for got to add that it is a compilation issue, it will not compile properly.

Use an IDE ,I bet you dont (otherwise it would mark compilation error immediatly with red -> you use return in void method ) and in this case you would see other errors.
(off: this would go to comment section however under 50reputation I am not allowed to do that. Stackoverflow should change this imo. )

First of all:
You marked function readInEntrants as public void so you can't use return inside.
You could either remove return entrantSet; instruction or change function definition to public Set<Entrant> readInEntrants.
Concerning problem you have:
Basing on comment you left on beatrice answer I think you have only parameterless constructor for 'Entrant' class, while you try to create it passing string as parameter.
new Entrant(currentEntrantLine)
What you need to do is define Entrant class constructor that accept String as it's argument. For example:
public Entrant(String dataToParse)
{
// here you parse data from string to entrant fields
}
On the side:
You use bufferedReader to read entire file line at once and that's ok, but then you define Scanner lineScanner to iterate through line elements and then use it only once.
This way for file... let's say:
One Two Three
Four Five Six
Your while loop would work like this:
Store "One Two Three" inside currentEntrantLine.
Create scanner that'll work on "One Two Three", and set it to use space as delimiter.
Use .next to "Finds and returns the next complete token" (see documentation) and then store value inside currentEntrantLine. This way contents of currentEntrantLine is "One". Not entire line.
In next iteration you would have scanner working on "Four Five Six" and "Four" as currentEntranceLine content.

It seems the constructor of entrant class does not have any argument. Pass String as an argument type in the constructor to set the String field inside the Entrant class .

Related

Trying to add substrings from newLines in a large file to a list

I downloaded my extended listening history from Spotify and I am trying to make a program to turn the data into a list of artists without doubles I can easily make sense of. The file is rather huge because it has data on every stream I have done since 2016 (307790 lines of text in total). This is what 2 lines of the file looks like:
{"ts":"2016-10-30T18:12:51Z","username":"edgymemes69endmylifepls","platform":"Android OS 6.0.1 API 23 (HTC, 2PQ93)","ms_played":0,"conn_country":"US","ip_addr_decrypted":"68.199.250.233","user_agent_decrypted":"unknown","master_metadata_track_name":"Devil's Daughter (Holy War)","master_metadata_album_artist_name":"Ozzy Osbourne","master_metadata_album_album_name":"No Rest for the Wicked (Expanded Edition)","spotify_track_uri":"spotify:track:0pieqCWDpThDCd7gSkzx9w","episode_name":null,"episode_show_name":null,"spotify_episode_uri":null,"reason_start":"fwdbtn","reason_end":"fwdbtn","shuffle":true,"skipped":null,"offline":false,"offline_timestamp":0,"incognito_mode":false},
{"ts":"2021-03-26T18:15:15Z","username":"edgymemes69endmylifepls","platform":"Android OS 11 API 30 (samsung, SM-F700U1)","ms_played":254120,"conn_country":"US","ip_addr_decrypted":"67.82.66.3","user_agent_decrypted":"unknown","master_metadata_track_name":"Opportunist","master_metadata_album_artist_name":"Sworn In","master_metadata_album_album_name":"Start/End","spotify_track_uri":"spotify:track:3tA4jL0JFwFZRK9Q1WcfSZ","episode_name":null,"episode_show_name":null,"spotify_episode_uri":null,"reason_start":"fwdbtn","reason_end":"trackdone","shuffle":true,"skipped":null,"offline":false,"offline_timestamp":1616782259928,"incognito_mode":false},
It is formatted in the actual text file so that each stream is on its own line. NetBeans is telling me the exception is happening at line 19 and it only fails when I am looking for a substring bounded by the indexOf function. My code is below. I have no idea why this isn't working, any ideas?
import java.util.*;
public class MainClass {
public static void main(String args[]){
File dat = new File("SpotifyListeningData.txt");
List<String> list = new ArrayList<String>();
Scanner swag = null;
try {
swag = new Scanner(dat);
}
catch(Exception e) {
System.out.println("pranked");
}
while (swag.hasNextLine())
if (swag.nextLine().length() > 1)
if (list.contains(swag.nextLine().substring(swag.nextLine().indexOf("artist_name"), swag.nextLine().indexOf("master_metadata_album_album"))))
System.out.print("");
else
try {list.add(swag.nextLine().substring(swag.nextLine().indexOf("artist_name"), swag.nextLine().indexOf("master_metadata_album_album")));}
catch(Exception e) {}
System.out.println(list);
}
}
Find a JSON parser you like.
Create a class that with the fields you care about marked up to the parsers specs.
Read the file into a collection of objects. Most parsers will stream the contents so you're not string a massive string.
You can then load the data into objects and store that as you see fit. For your purposes, a TreeSet is probably what you want.
Your code will throw a lot of exceptions only because you don't use braces. Please do use braces in each blocks, whether it is if, else, loops, whatever. It's a good practice and prevent unnecessary bugs.
However, everytime scanner.nextLine() is called, it reads the next line from the file, so you need to avoid using that in this way.
The best way to deal with this is to write a class containing the fields same as the json in each line of the file. And map the json to the class and get desired field value from that.
Your way is too much risky and dependent on structure of the data, even on whitespaces. However, I fixed some lines in your code and this will work for your purpose, although I actually don't prefer operating string in this way.
while (swag.hasNextLine()) {
String swagNextLine = swag.nextLine();
if (swagNextLine.length() > 1) {
String toBeAdded = swagNextLine.substring(swagNextLine.indexOf("artist_name") + "artist_name".length() + 2
, swagNextLine.indexOf("master_metadata_album_album") - 2);
if (list.contains(toBeAdded)) {
System.out.print("Match");
} else {
try {
list.add(toBeAdded);
} catch (Exception e) {
System.out.println("Add to list failed");
}
}
System.out.println(list);
}
}

Compare files string by string

I have two files:
Grader.getFileInfo("data\\studentSubmissionA.txt");
Grader.teacherFiles("data\\TeacherListA.txt");
Both contain a list of math problems, but the TeacherList is unsolved in order to check that the StudentSubmission was not altered from the original version.
studentSubmission is sent to the Grader class and the method currently looks like this:
public static void getFileInfo(String fileName)
throws FileNotFoundException {
Scanner in = new Scanner(new File(fileName))
while (in.hasNext()) {
String fileContent = in.nextLine();
}
and the TeacherFiles method looks like
public static void teacherFiles(String teacherFiles)
throws FileNotFoundException{
Scanner in = new Scanner(new File(teacherFiles));
while (in.hasNext()){
String teacherContent = in.nextLine();
String line = teacherContent.substring(0, teacherContent.indexOf('='));
}
I don't know how to get these methods to another method in order to compare them since they're coming from a file and I have to put something in the method signature to pass them and it doesn't work.
I tried putting them in one method, but that was a bust as well.
I don't know where to go from here.
And unfortunately, I can't use try/catches or arrays.
Is it possible to send the .substring(0 , .indexof('=')) through the methods?
Like line = teacherFiles(teacherContent.substring(0 , .indexof('='))); Is it possible to do this?
Think in more general terms. Observe that your methods called getFileInfo and teacherFiles, respectively are the very same except a few nuances. So why do not we think about finding the optimal way of merging the two functionalities and handling the nuances outside of them?
It is logical that you cannot use arrays as you need to know the number of elements of your array before you initialize it and your array would have already been initialized when you read the file. So using an array for this task is either an overkill (for example you allocate 1000 elements in your memory and you use only 10 elements) or insufficient (if you create an array of 10 elements, but you would need 1000). So, due to the fact that you do not know the number of rows in advance you need to use another data structure for your task.
So create the following method:
public static AbstractList<String> readFile(String filePath) throws FileNotFoundException, IOException {
Scanner s = new Scanner(new File(filePath));
AbstractList<String> list = new ArrayList<String>();
while (s.hasNext()){
list.add(s.next());
}
s.close();
return list;
}
Then use the method to read the student file and to read the teacher file. Store the results into two separate AbstractList<String> variables, then iterate through them and compare them as you like. Again, think in more general terms.

CSV to a String Array - JAVA

I have a CSV file which has only one column with 100+ rows. I would like to put those values in an one dimensional array(only if its possible). So that it works as same as if I wrote a string array manually. I.e.
String[] username = {'lalala', 'tatata', 'mamama'}; //<---if I did it manually
String[] username = {after passing the CSV values}; //<---I want this like the above ones.
Then later I would like to be able to initialized that class to a different class, say if the class that holds the array is called ArrayClass, I would like to be able to initialized this to different class, like this --
public class MainClass{
ArrayClass array = new ArrayClass();
//Then I would like to be able to do this
someMethod(array.username);
}
I know I asked a lot of things but I seriously appreciate all your help. Even if you see this question and say THIS IS BS. Oh and one more thing I would prefer it to be in JAVA.
It might be easier to use an arraylist rather than an array as you dont have to worry about number of rows. An array has a fixed size that cant be changed. i.e ArrayList
As you have only one column you will not need to worry about commas in csv
Example code would look something like this:
import java.util.*;
import java.io.*;
public class MyClass {
private ArrayList<String> MyArray = new ArrayList<String>();
private Scanner scan;
public MyClass(){
try {
scan = new Scanner(new File("MyFile.csv"));
} catch (IOException ioex) {
System.out.println("File Not Found");
}
}
public ArrayList<String> getArray() {
while (scan.hasNext()) {
Scanner line = new Scanner(scan.nextLine());
MyArray.add(line.next());
}
return MyArray;
}
}
And in the main:
MyClass f = new MyClass();
System.out.println(f.getArray());
If it's just a csv you can use the split method of string with a proper regex.
Please do check the split method
The first half of your question is easy and can be handled in a number of different ways. Personally, I would use the Scanner class and set the delimiter to be ",". Create a new Scanner Object and then call setDelimiter(",") on it. Then simply scan through the tokens. See the example on the documentation. This method of doing things is effective because it handles reading in the file and separating it based on your criteria (the ',' character).

Using User input for the reflection process in java

basically am trying to make java command prompt. Suppose user enters as input from the user:
new x java.util.ArrayList
here x is the object name and java.util.ArrayList is the class. So this script inputed by the user means create an object of class java.util.ArrayList.
Now suppose that user enter:
new x java.util.ArrayList int:5
means create an object x of the java.util.ArrayList and make its size 5. Like this i want that everytime i input something related to object creation as input i should be able to create class its object and its method based on the input that the user does. Am new to java and reflection so kindly help! here is the code i thought so far using my mind:
public static void token_classification() throws ClassNotFoundException
{
my_hash = new HashMap();
Keep_Obj_Info = new HashMap();
if(expression_keeper[0].equalsIgnoreCase("new"))
{
my_hash.put("Object", expression_keeper[1]);
Class Obj= Class.forName(expression_keeper[2]);
Keep_Obj_Info.put("Modifier", Obj.getModifiers());
Keep_Obj_Info.put("Package",Obj.getPackage());
////????
Constructor[] constructors = Obj.getConstructors();
}
else
if(expression_keeper[0].equalsIgnoreCase("call"))
{
}
else
if(expression_keeper[0].equalsIgnoreCase("print"))
{
}
else
{
System.out.println("Invalid Script!");
}
}
ExpressionKeeper is basically a String array that keeps the user input in tokenized form. Meaning anything next to a white space to a new location.
Well for Object creation in java; the constructor and it's arguments are required.
you can have a generic framework which will accept input from command prompt and interpret them means find out the data type of the input ex : number/string/char/boolean etc..
Also your framework should know the argument index for example say a constructor has 2 parameter and one is string and another is int. and say first parameter is int and 2nd parameter is String and while passing the parameter from the command line the user first pass string and then int in that scenario your program should be smart enough to properly arrange them in order. So many such things you need to take care of....Now coming to the example which you have mentioned for ArrayList you can write a program as follows : (I have just given you a pseudocode you can implement your own way)
{
int howManyParametersFromCommandLine = getnoParameterCount; //it will maintain no.of parameters passed from command line
String[] parametersFromCommandLine = getParametersFromcommandLine(); // Ex : {1,"ABC",new Double(80.0d)};
List<Class> parameterTypesList = parseParameters(parametersFromCommandLine); //This will identify type of each of the parameter
Class clazz = Class.forName("youClassName");
Constructor[] cons = clazz.getConstructors();
for(Constructor c : cons)
{
Class[] parameterTypes = c.getParameterTypes();
if(parameterTypes.length == howManyParametersFromCommandLine)
{
//try to match the parameter type in parameterTypesList with parameterTypes if this matches then
boolean typeMatchingAndSequecneSucess = matchParameters(parameterTypes,parameterTypesList);
if(typeMatchingAndSequecneSucess)
{
if(c.isAccessible())
{
Object[] initargs = parseAndRetActualParamValue(parametersFromCommandLine);
return c.newInstance(initargs);
}
}
}
}
}
Hope this will help you !!
You may want to use the Interpreter design pattern. It is used just for that.
The Interpreter is a bit complex, but will ensure you code interpretation works right. Also, it gives you a easy inclusion of new commands.
Take a look at here: http://en.wikipedia.org/wiki/Interpreter_pattern
Hope I could help.

Picking up from where I left off when reading a file in Java

I am trying to read info from a file and create objects out of that information. Every 6 or so lines of the file is a different unit, meaning that the first set of lines are relevant to object A, the next set to object B, and so on.
I can read from the file and create my object just fine--for the first set. My problem is that I don't know how to get the reader to pick up from the spot it left off at when creating the next object...
(Note: the read() method which creates the file is part of the new object being created, not in a main() or anything like that). Here are the relevant bits of code:
The driver:
public class CSD{
public static void main (String[] argv){
Vector V=new Vector(10);
CoS jon=new CoS();
jon.display();
}//end main
}
which calls CoS, whose constructor is:
public CoS(){
try{
String fileName=getFileName();
FileReader freader=new FileReader(fileName);
BufferedReader inputFile=new BufferedReader(freader);
this.read(inputFile);
setDegree(major);
setStatus(credits);
} catch(FileNotFoundException ex){
}//end catch
}
Which calls both read() and getFileName():
public void read(BufferedReader inputFile){
try{
int n;
super.read(inputFile);
String str=inputFile.readLine();
if (str!=null){
n=Integer.parseInt(str);
setCredits(n);
str=inputFile.readLine();
setMajor(str);
}//end if
}catch(IOException ex){}
}//end method
public String getFileName() {
Scanner scan = new Scanner(System.in);
String filename;
System.out.print("Enter the file name and path ==> ");
filename = scan.nextLine();
System.out.println("");
return filename;
}
Thanks in advance, guys!
Why not use ObjectInputStream and ObjectOutputStream? Or any kind of real serialization?
javadoc: http://docs.oracle.com/javase/6/docs/api/java/io/ObjectOutputStream.html
example code: http://www.javadb.com/writing-objects-to-file-with-objectoutputstream
Basically, since you write your objects to a file and want to take care of the lines where they are located, I'll suggest a few other serialization alternatives.
One is the Object * Stream - you create a ObjectStream on a File and just write objects thru it. Later when you read, you read the objects in the reverse order you wrote them and they will come back just as you wrote them.
Another is to implement Serializable. Remember that transient keyword? Use it on fields you do not want to save to the file.
And then there's the raw "by hand" approach where you save only the things you want to save and reconstruct the objects later by passing these initialization values to their constructor. Kinda like people suggested that you make the file line a argument to the ctor :)
EDIT:
guess writing with Object*Streams requires you to implement Serializable or Externalizable.
but if the example code isn't clear enough, ask :)

Categories