List of class objects - java

I'm stuck.. I trying to parse a text from file in words, but save it in List of objects. Whether it is possible to do so?
public class Text {
public static List<Words> words = new ArrayList<Words>();
}
public class Words {
private String path;
private String[] inside;
private BufferedReader in;
public Words(String path, String[] inside) {
this.inside = inside;
this.path = path;
}
public String[] splittinIntoWords() throws IOException {
in = new BufferedReader(new FileReader(path));
String s;
while ((s = in.readLine()) != null) {
inside = s.split(" ");
//System.out.println(Arrays.toString(inside));
}
return inside;
}
}
and main class
public class Main {
public static void main(String[] args) throws IOException {
String file_name = "book.doc";
String[] inside = null;
Words w = new Words(file_name, inside);
w.splittinIntoWords();
Text.words.add(w); //after add in list i have a reference.
System.out.println(Text.words.toString());
}
}
i do smthg wrong. I understand how to do this with List of Strings
tell me please, it is possible, to add text splitting into words in List of Words

You’re overwriting the array of words Words.inside with each line you read. You need to add the output of split() to a List every time round the while loop, not just at the end.
I would expect your code to display the words in the last line of your file, but possibly it has a blank last line, in which case you will see nothing.
Also, I assume your "book.doc" is not really a .doc format file—word processor files need special parsing; what you have written will only work on plain text files.

there is several things wrong with your code.
Text.words shouldn't be static. Every instance of text consists of a different collection of words.
When you make a "Collection of Words", then it should be Collection< Word>. Because every item inside the collection is just a single item.
but then again, Collection< Word> is just the same as Collection< String>. So use that.
"path", "in" should not be member variables of "Words". Just use them locally in your method. Especially since you never closed "in".
you're overwriting whatever is in "inside" for each line in your file that you loop over. When you have your "Collection< String> words", then just do words.addAll(inside); in
your loop.
Yes, I know this is not an answer, but I'm trying to point you in the right direction. This might help you more in the long run.

Related

How do I access an array within an array?

Say I have a .txt file that has information being split by a comma as such:
IN,Indiana,6634007
While this is a snippet which accesses that file and splits it:
for(int i=0; i < count; i++) {
line = bufferedReader2.readLine();
String space[] = line.split(",");
String abb = space[0];
String nme = space[1];
int pop = Integer.parseInt(space[2]);
states[i] = new State(abb, nme, pop);
}
The purpose of that was so that all the information in the txt file could be accessed, so for example this code would print exactly whats present on the .txt file:
System.out.println(states[0]);
would print:
IN,Indiana,6634007
My question is, how would I have it so that I can access the specific part of the array as in how would I print lets say just the name "Indiana" or the population "6634007"?
P.S I'm sorry if the title of my question did not make sense, I did not exactly know how to word it.
Somewhere, you have a class called State. states is an Array of this class. So you can add a getter to State:
public int getPop() {
return pop;
}
And call it on your Object like this:
System.out.println(states[0].getPop());
as states[0] is simply a State object.
Add more getters to access different fields.
if you just want to print every single line, you can try this like below:
public static void main(String[] args) throws Exception {
BufferedReader reader = new BufferedReader(new FileReader("data.txt"));
String line = null;
List<String> list = new ArrayList<String>();
while((line = reader.readLine()) != null ) {
list.add(line);
}
System.out.println(list.get(0));
// TODO realease resources
}
From your question what i can realise is, you are using State class to store the information. In such case, check the state class where the first parameter value is stored. Later to print the corresponding information, access its object variable as SapuSeven mentioned.
For eg.
public class State{
public String a;
public String b;
public int c;
public State(String x, String y, int z){
a=x;
b=y;
c=z;
}
}
now u can access like
System.out.println(states[0].b);
for printing the name of city
OR
you can simply print the value using index like this
System.out.println(states[0].split(",")[2]);

How to pass text file data from one class to another

I'm trying to create a program that reads a text file and then outputs stats about the text file. I'm getting stuck on the beginning. In this assignment, we were told that we just need to read using the scanner in one class and the create "tokens" to be passed and used in other classes for calculations. I'm not entirely sure how to do that. This is my code so far for reading the file inside one class:
private String s;
public void analyzeBookText(Scanner input) {
while(input.hasNext()) {
input.useDelimiter(".|!|?");
s = input.next();
if(input.next().equals("$$$END$$$")) {
break;
}
}
}
public String getS() {
return s;
}
So I have string s be just one sentence. Then I'm trying to access s in a different class by creating a String instance variable and this constructor:
public SentenceTally() {
BookMain sentence = new BookMain();
s = sentence.getS();
}
However, when I try to use s in other methods I get a stackoverflow error. How can I properly use data from the scanner in one class in methods for another class? Thanks!
You are half way there. Next, what you need is to read the text file and store it into an array. Since your school mentioned tokens, you may read line by line from the text file, then split each line (if your data file only has one line, then just tokenize that one line of data) into tokens (represented as array):
String[] tokens = line.split(delimiter);
You may need to convert the tokens to int array or double array first being using it for calculations.
Pass tokens array as an argument to your other methods for calculation:
public void calculate(int[] tokens){
//your calculations in Java
}
To pass your data to other classes:
BookMain book = new BookMain();
book.analyzeFile(yourScanner);
SomeClass c = new SomeClass();
c.calculate(book.getTokens()); //create a getter for tokens in BookMain first

How do I use this method? (the method takes a text file and convert it into a string)

I'm currently in a High School level Java course. I've been doing plenty of research here, on Stack Overflow, trying to work through a project i'm currently assigned. The project consists of making modifications to, and searching through, various words pulled from an encyclopedia file. This is what I am having trouble with, the very basic form of this project. I already found the method in which to solve this problem, but i wasn't able to find a good way of implementing it. This is a copy of the code i found here: (the third method down contains the portion i took from this site)
class word
{
public String newString;
EasyReader fileIn = new EasyReader("Encyclopedia.txt");
EasyWriter fileOut = new EasyWriter("writeHere.txt");
String fileName="Encyclopedia.txt";
private String onFile;
public word()
{
onFile="";
}
public word(String s)
{
onFile=s;
}
String file = "Encyclopedia.txt";
private String readFile(String file) throws IOException
{
BufferedReader reader = new BufferedReader(new FileReader(file));
String line=null;
StringBuilder stringBuilder = new StringBuilder();
String is=System.getProperty("line.seperator");
while((line=reader.readLine())!=null)
{
stringBuilder.append(line);
stringBuilder.append(is);
}
newString=stringBuilder.toString();
return stringBuilder.toString();
}
}
So, the question: how do i use this method? i know it sounds silly, but how do run this method and then use the data later? It is supposed to take a given text file and return a string, but i'm not even sure how to get the return value after it has processed.
Any help would be greatly appreciated. I made an account here just to ask this question. If i need to post this somewhere else, or if there is a better site to use to find an answer and some more basic help, please let me know. Thanks,
-Ethan
The readFile method seems to be doing multiple things at once. It accepts a file argument which overrides the member variable with the same name. Then it reads the file into a String and sets the newString member variable to the result before returning the same result.
So I would recommend first deciding whether the method should return the data or set the member variable. If multiple methods are going to be using the result, it might be useful to use the member variable, otherwise go the return route. Also, you can probably remove the file member variable since it is ignored by the method.
You can rewrite the method to look like this (I just removed the newString=stringBuilder.toString(); line, and I changed it to static since it can be):
private static String readFile(String file) throws IOException
{
BufferedReader reader = new BufferedReader(new FileReader(file));
String line=null;
StringBuilder stringBuilder = new StringBuilder();
String is=System.getProperty("line.seperator");
while((line=reader.readLine())!=null)
{
stringBuilder.append(line);
stringBuilder.append(is);
}
return stringBuilder.toString();
}
And wherever you need to use it call it like this (remember to catch the IOException):
try {
String someString = readFile("filename.txt");
} catch(IOException e) {
// handle error
}
Remember it must be called from inside the same class unless you change private to public.
Also, it might be worth reading and following a standard code style. It can really help by distinguishing between different types of variable for example.
Actual method that read string from file is: "readFile". And in your class, you are not calling that.
private String readFile(String file) throws IOException
You can pass file name as parameter, and It will returns read string.
So, how about modify your word(String s), and add method that will return actual result of read file?
public word(String s)
{
onFile=s;
newString = readfile(onFile);
}
public getNewString(){
return newString;
}
Try this:
String file ="/path/to/file.csv"
word myWord = new word();
o = myWord.getClass().getDeclaredMethod("readFile");
o.setAccessible(true);
Object r = o.invoke(myWord);
//print result

Better way to split my results from reading file?

I have a function that reads through a file, and gathers the results into an array list.
The array list looks like this (data)
[12, adam, 1993, 1234, bob, 1992]
I then need to load these details into new objects called patients. This is the current method I have so far for putting each separate array list item into its own patient, yet it keeps bugging me with an error saying I am passing in String String Int, and it needs to be a String.
s looks like this
12, adam, 1993
And this is the code
public void loadPatients()throws Exception
{
ArrayList<String> data = IO_Support.readData("PatientData.txt");
System.out.println(data);
for(String s : data)
{
Sytem.out.println(s);
patientList.add(new Patient(s));
}
}
Is there a way to push my array list result into a string for passing into the patient object, or should I use a different way to split the string results?
Read data looks like this
public static ArrayList<String> readData(String fileName) throws Exception
{
ArrayList<String> data = new ArrayList<String>();
BufferedReader in = new BufferedReader(new FileReader(fileName));
String temp = in.readLine();
while (temp != null)
{
data.add(temp);
temp = in.readLine();
}
in.close();
return data;
}
while (temp != null)
{
temp = in.readLine();
}
First thing, You are never adding your input to the ArrayList.. This while loop makes no sense.. It is just reading user input, and swallowing it on every occassion..
Plus, after seeing your exception, its sure that you are using a 1-arg constructor of Patient class which is not there.. There are only 0-arg constructor and 2-arg constructor in Patient class.. You need to use them indeed.
See this code in loadPatient method.. You need to add a 1-arg constructor in your Patient class to get it compiled..
patientList.add(**new Patient(s)**); --> Will not work
So, in your Patient class, add: -
public Patient(String s) {
this.s = s;
}
this.s is the instance variable to store s that you passed..

To have efficient many-to-many relation in Java

How can you make the efficient many-to-many -relation from fileID to Words and from word to fileIDs without database -tools like Postgres in Java?
I have the following classes.
The relation from fileID to words is cheap, but not the reverse, since I need three for -loops for it.
alt text http://img191.imageshack.us/img191/4077/oliorakenne1.png
My solution is not apparently efficient.
Other options may be to create an extra class that have word as an ID with the ArrayList of fileIDs.
Reply to JacobM's answer
The relevant part of MyFile's constructors is:
/**
* Synopsis of data in wordToWordConutInFile.txt:
* fileID|wordID|wordCount
*
* Synopsis of the data in the file wordToWordID.txt:
* word|wordID
**/
/**
* Getting words by getting first wordIDs from wordToWordCountInFile.txt and then words in wordToWordID.txt.
*/
InputStream in2 = new FileInputStream("/home/dev/wordToWordCountInFile.txt");
BufferedReader fi2 = new BufferedReader(new InputStreamReader(in2));
ArrayList<Integer> wordIDs = new ArrayList<Integer>();
String line = null;
while ((line = fi2.readLine()) != null) {
if ((new Integer(line.split("|")[0]) == currentFileID)) {
wordIDs.add(new Integer(line.split("|")[6]));
}
}
in2.close();
// Getting now the words by wordIDs.
InputStream in3 = new FileInputStream("/home/dev/wordToWordID.txt");
BufferedReader fi3 = new BufferedReader(new InputStreamReader(in3));
line = null;
while ((line = fi3.readLine()) != null) {
for (Integer wordID : wordIDs) {
if (wordID == (new Integer(line.split("|")[1]))) {
this.words.add(new Word(new String(line.split("|")[0]), fileID));
break;
}
}
}
in3.close();
this.words.addAll(words);
The constructor of Word is at the paste.
Wouldn't a more efficient approach be to assign the link from Word to MyFile at the point that you know the Word is in the File? That is to say, how do you build the list of Words in the MyFile object? If you're reading the words in to the MyFile out of, say, a file on the filesystem, than as you read in each word, you assign its MyFile to the current file.
//within MyFile constructor or setter for Words
while (//there's another word to add) {
Word newWord = new Word(//read word from file);
words.add(newWord);
newWord.setMyFile(this);
}
This is akin to the typical way to manage a bidirectional parent-child relationship:
//in Parent
public void addChild(Child child) {
myChildren.add(child);
child.setParent(this);
}
It might help if you show us how you build the MyFile object.
Edited after you added the code that builds the list of Words:
OK, so having seen the code that builds your Words, I don't think setting up the relationship is the source of your inefficiencies. It looks like you are setting up the relationship in exactly the way I suggested (as you add each word, you give that word the fileID of the corresponding file).
It looks like the source of your inefficiencies are that, for each word, you have to match it up with various things that you currently have in a set of files (e.g. WordToWordId). So for every word you have to loop through every line of that file, and find the match. This is certainly inefficient.
The better approach is to have those pairings in memory in a HashMap, initialized at startup. That way, if you have a particular word and need the corresponding ID, or vice versa, you look them up in your HashMap, which is a constant-time operation. Similarly, for each word, you are looping through every file; again, do that loop ONCE, and store the result in a HashMap. Then lookups become constant time.
Both classes should override hashCode and equals. Thus you will decide what is equal.
Then you will create a set in each of your classes.
public class MyFile implements Comparable<MyFile> {
//your fields here
Set<Word> words = new HashSet<Word>(0);
//Remember to override hashCode and equals
}
public class Word implements Comparable<Word> {
//your fields here
Set<MyFile> words = new HashSet<MyFile>(0);
//Remember to override hashCode and equals
}
In your sets now you will have all the MyFiles.words and otherway around, all the Words.myFile
I think you want that the file know it's words and the words know the files where it is used.
public class File {
private List<Word> words;
public File(){
words=new Vector<Word>();
}
/**
*The method add word to word list.
**/
public addWord(Word word){
this.words.add(word);
word.addFile(this);
}
}
public class Word{
List<File> files;
public addFile(File file){
this.files.add(file);
}
}
or vice versa... but you should question GRASP Design pattern.Maybe your data type is wrong (I dont say wrong because itis your desing,so i respect).

Categories