Help with arrays, static/non staic please...

Hi everyone,

I'm relatively new to java and have been having some trouble with a program I'm creating. I'm trying to read a list of words from a text file into a 2D array and then use them to form the basis of a simple translator program with a GUI.

One recurring problem early on was keeping the static/non static methods and variables straight. I can't seem to find a way to read the words into an array, then use methods in the same or different class to access them (look up, compare, etc.). Finally I had to resort to having one main file read all the entries and write them line by line (as well as a few appropriate methods) to a new .java file, which turns out to be a pain (mainly cuz thats alot of fileOut.print() statements).

I'd really like to avoid having to have a file to write to a file for my program, as in the algorithm i just described. If anyone has any insights, advice, or examples of similar working programs, PLEASE reply. Thanks.

[987 byte] By [commandy3a] at [2007-9-29 18:40:26]
# 1
Reading a list of words from a file is pretty trivial.Why a 2D array? What format is the file in? (one word per line? one word per column per line?)
paulcwa at 2007-7-15 18:32:58 > top of Java-index,Other Topics,Algorithms...
# 2
Why not a 2D array? Think an ArrayList would work better? Yes, there is 1 row per line and 3 columns per line. I separated them by spaces " " and used split(). I know it must seem pretty stupid, sorry.
commandy3a at 2007-7-15 18:32:58 > top of Java-index,Other Topics,Algorithms...
# 3

> Why not a 2D array?

Well, you said a list of words. That's usually 1D. What's the second dimesion being used for?

> Think an ArrayList would work better?

Probably, but not for that reason.

> Yes, there is 1 row per line and 3 columns per

> line. I separated them by spaces " " and used split().

But why? What do the columns mean?

paulcwa at 2007-7-15 18:32:58 > top of Java-index,Other Topics,Algorithms...
# 4
Sorry for not being clear enough. I have the first two columns reserved for the two guide words in Latin (the language I'm translating) and the last one as the English definition. They're separated by spaces. Thanks.
commandy3a at 2007-7-15 18:32:58 > top of Java-index,Other Topics,Algorithms...
# 5
Then rather than a 2D array, how about a List of objects that encapsulate those two guide words and the English translation?
paulcwa at 2007-7-15 18:32:58 > top of Java-index,Other Topics,Algorithms...
# 6
I'm not too familiar with Lists but I'll check it out. Thanks.
commandy3a at 2007-7-15 18:32:58 > top of Java-index,Other Topics,Algorithms...
# 7
What kind of List would it be the best to use and why?
commandy3a at 2007-7-15 18:32:58 > top of Java-index,Other Topics,Algorithms...
# 8

> What kind of List would it be the best to use and why?

My guess would be that you might want to use a HashMap (or maybe two). You could put the sets of words in your own object (like so) (I'm going to ignore the two latin words per set)

public class WordSet {

String latin, english;

public WordSet(String Latin, String English) {

latin1=Latin; english=English;

}

public String getLatin() { return latin; }

public String getEnglish() { return english; }

}

Create them soWordSet myWord1 = new WordSet("canis","dog"), myWord2 = new WordSet("iridis","rainbow");

put them in the hashmap soHashMap latinMap = new HashMap(), englishMap= new HashMap();

latinMap.put(myWord1.getLatin(), myWord1);

latinMap.put(myWord2.getLatin(), myWord2);

englishMap.put(myWord1.getEnglish(), myWord1);

englishMap.put(myWord2.getEnglish(), myWord2);

and use them soSystem.out.println("Dog in latin is "+((WordSet)englishMap.get("dog")).getLatin());

and if I haven't made any mistakes in this untested code, it should print out

Dog in latin is canis

bbrittaa at 2007-7-15 18:32:58 > top of Java-index,Other Topics,Algorithms...
# 9
I was so busy shoowing you code, I didn't tell you why use HashMap. The reason is that you can do quick lookups for a word without having to scan an entire list.
bbrittaa at 2007-7-15 18:32:58 > top of Java-index,Other Topics,Algorithms...
# 10
Thanks for the advice. I'm going to read them from the text file though, I'll have to see how all that works. If I run into any more major snags I'll post a new thread prob. Thanks again to both of you.
commandy3a at 2007-7-15 18:32:58 > top of Java-index,Other Topics,Algorithms...
# 11

> englishMap.put(myWord1.getEnglish(), myWord1);

> englishMap.put(myWord2.getEnglish(),

I'm running into some major problems with the HashMap route, and I would GREATLY appreciate it if you could help me some more. I have three files, and I'll just post some of the code so you can take a look and see what you think.

The first one is a simple GUI that I created. Not much excitement going on there... I just am going to have an execute method waiting for the button to be pressed. That's set up nicely in netBeans.

Next, I have a method called Noun based off the example you gave earlier. It's like this:

public class Noun {

private String latin1, latin2, english;

public Noun(String lat1, String lat2, String eng) {

latin1 = lat1;

latin2 = lat2;

english = eng;

}

public String getLatinNomSing() {

return latin1;

}

public String getLatinGenSing() {

return latin2;

}

public String getEnglish() {

return english;

}

}

Short, simple, to the point. Finally, I have the tricky one: the file that does the reading and handles most of the functions. It's relatively lengthy, but I think I can post all of it.

import java.io.*;

import java.util.HashMap;

public class WordReader {

private static BufferedReader fileIn;

private static String fileName = "(path to file)";

private HashMap latinMap;

private HashMap englishMap;

public void read() {

try {

openInputFile(fileName);

if (fileIn == null) {

return;

}

int count = readDictionary();

fileIn.close();

}

catch(IOException e) {

}

}

private static void openInputFile(String fileName) {

try {

fileIn = new BufferedReader(new FileReader(fileName));

}

catch (FileNotFoundException e) {

}

}

private int readDictionary() throws IOException {

String line;

int count = 0;

while ((line = fileIn.readLine()) != null) {

String split[] = line.split(" ", 3);

Noun noun = new Noun(split[0], split[1], split[2]);

latinMap.put(split[0], noun);

englishMap.put(split[2], noun);

count++;

}

return count;

}

public String lookup(String engWord) {

read();

Noun latNoun = (Noun)latinMap.get(engWord);

String latWord = latNoun.getLatinNomSing();

return latWord;

}

public static void main(String[] args) {

WordReader parser = new WordReader();

String latWord = parser.lookup("word to look up");

System.out.println(latWord);

}

}

NOTE: I put in the main() for test purposes, and to no avail yet.

So, one problem that I can't figure out is this: when the while

loop inside readDictionary

reads a word and puts it into the HashMap, it uses the same name, "noun" every time! I think that's one problem. There are probably more, and I know my code design probably needs some work. I'm a novice. But any help, like I said, would be greatly appreciated. Alright, thanks in advance.

STATIC and EXCEPTIONS are the scourge of java, at times I'm ready to kill this blasted thing.

commandy3a at 2007-7-15 18:32:58 > top of Java-index,Other Topics,Algorithms...
# 12
Oh, and one thing I forgot to mention, if anyone knows of perhaps a better way to get these words into the program than using a .txt file: that would be great. I somehow get the feeling that IO is not java's strong point hehe...
commandy3a at 2007-7-15 18:32:58 > top of Java-index,Other Topics,Algorithms...
# 13

You may want to make the latin1, latin2, and english fields of Noun to be final.

They effectively are already, and it's good practice anyway.

you're using fields as global variables, which is a good source of bugs. You really don't need fileIn to be a field -- you could just as easily (and more cleanly) pass the Reader as an argument to readDictionary.

In two places, you're silently catching exceptions. You should at least display a warning message.

Putting read() in your lookup method means that you re-load the dictionary on every lookup. That's inefficient. You may find it better to put read() in WordReader's constructor.

> when the while loop inside readDictionary reads a word and puts it

> into the HashMap, it uses the same name, "noun" every

> time! I think that's one problem.

Not really. Using the same name isn't a problem. It still just ends up being some bits on the stack.

Trying to use different names would make your code ugly fast, making it less maintainable and not gaining anything.

paulcwa at 2007-7-15 18:32:58 > top of Java-index,Other Topics,Algorithms...
# 14

> STATIC and EXCEPTIONS are the scourge of java, at

> times I'm ready to kill this blasted thing.

Exception handling is a great attribute of java. Do you really want code flaws to show up only by surprise?

Static is an essential part of OOP.

> if anyone knows

> of perhaps a better way to get these words into the

> program than using a .txt file: that would be great. I

> somehow get the feeling that IO is not java's strong

> point hehe...

Java IO is fine. Touching the filesystem is always going to be slow.

If you have a lot of words in your dictionary, think about using a relational database.

paulcwa at 2007-7-15 18:32:59 > top of Java-index,Other Topics,Algorithms...
# 15

Thanks for your help guys. I had to make some big changes, but got everything pretty much finished. The translator now works, except I have one problem:

I had to do away with the two HashMaps and just use one, in which i simply stored two strings, the latin and the english. The problem with the way you suggested it was, the strings were being associated with their respective noun object - which is actually what I want it to do, except that the lookup is inside a method than the reading and creation of the Nouns. Which means that the Noun objects that are created when reading the file go out of scope when the method exits (it took me a little while to figure out where this NPException error was coming from), and there's really no good way I can think of to have the noun objects stick around for the lookup. SO, can anyone think of any possiblities?

commandy3a at 2007-7-19 16:59:21 > top of Java-index,Other Topics,Algorithms...
# 16

I'm not convinced that your description of the problem is accurate.

If you're creating objects and storing them in a hashtable, they shouldn't go out of scope. Objects don't really have scope anyway. If nothing refers to them, they can get GC'd, but that's not the same thing, and the hashtable should be referring to them anyway. Or am I misunderstanding what you're saying?

paulcwa at 2007-7-19 16:59:21 > top of Java-index,Other Topics,Algorithms...
# 17

(Assuming I keep my old code, which did not work:)

[code]

import java.io.*;

import java.util.HashMap;

public class WordReader {

private static String fileName = "C:\\My Documents\\AP_JONES\\LatinTranslator\\LatinTranslator\\nouns.txt";

private HashMap latinMap = new HashMap();

private HashMap englishMap = new HashMap();

public WordReader() {

readDictionary();

}

private void readDictionary() {

String line;

try {

BufferedReader fileIn = new BufferedReader(new FileReader(fileName));

if (fileIn == null) {

System.out.println("*** FATAL ERROR: Empty input file. ***");

return;

}

try {

while ((line = fileIn.readLine()) != null) {

String split[] = line.split(" ", 3);

Noun noun = new Noun(split[0], split[1], split[2]);

latinMap.put(noun.getLatinNomSing(), noun);

englishMap.put(noun.getEnglish(), noun);

}

fileIn.close();

// ***** Putting the call to something like (Noun)englishMap.get("anyword").getLatinNomSing()

// works here, but not down in the lookup() method, where I get a NullPointerException.

}

catch (IOException e) {

System.out.println("*** FATAL ERROR: An IO Exception has occurred. ***");

return;

}

}

catch (FileNotFoundException e) {

System.out.println("*** FATAL ERROR: Could not open input file. ***");

return;

}

}

public String lookup(String engWord) {

return ((Noun)englishMap.get(engWord)).getLatinNomSing(); // doesnt work

}

public static void main(String[] args) {

WordReader parser = new WordReader();

String latWord = parser.lookup("light");

System.out.println(latWord);

}

}

commandy3a at 2007-7-19 16:59:21 > top of Java-index,Other Topics,Algorithms...
# 18

Nevermind, I found and fixed the problem. But I have a question. When I use a JFrame GUI, it runs with no errors. Yet when I create an Applet GUI with the exact same code, I get a SecurityAccessException or something to that effect. FilePermission. I would assume that applets cant touch the filesystem? Thanks.

commandy3a at 2007-7-19 16:59:21 > top of Java-index,Other Topics,Algorithms...
# 19

> I would assume that applets cant touch the filesystem?

Right.

There are ways around this, which I've never tried, but which involve signing applets and/or changing the security rules around your use of applets.

But I'd argue that it's not worth doing those, because it's kind of missing the point of applets. Once you're running stuff off the hard drive, use an executable jar. If you want to use an applet, it would probably make more sense to most of the functionality on the server side (e.g., as a servlet) and then just use the applet as a thin client, if at all.

paulcwa at 2007-7-19 16:59:21 > top of Java-index,Other Topics,Algorithms...
# 20

You could speed things up alot by using a differnet method for reading your rows. The split() method is quite slow compared to other techniques.

Heres a real simple one which is definately prone to errors, but will work fast with well formatted input...

String text = "abc def ghi";

int idx = 0;

while (idx < text.length()) {

int next = text.indexOf(' ',idx);

next = next < 0 ? text.length() : next;

System.out.println(text.substring(idx,next));

idx = next + 1;

}

IanSchneidera at 2007-7-19 16:59:21 > top of Java-index,Other Topics,Algorithms...
# 21

Ok, my program is working great but I want to try using a database. I've spent a few hours researching how to do that... I'm clueless. I have some experience with mySQL, php, and Access... so I'm not completely database-illiterate. But using them in java is something I haven't figured out yet. Here's what I've got so far, and it's throwing a SQL exception. A very important feature for this implementation is that it has to be able to run as an executable jar (I've already got that working) on any computer with minimal fuss. I.e., I don't want to go adding anything to the classpath or ODBC of any given computer that I take my program to and run it on. Welll.... merry Christmas everyone!

try {

String mdb = "database.mdb";

try {

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

}

catch (ClassNotFoundException e) {

System.out.println("Class not found.");

}

String url = "jdbc:odbc:DRIVER={Microsoft Access Driver (*.mdb)};DBQ=database.mdb";

Connection dbConnection = DriverManager.getConnection(url, "dba","sql");

catch (SQLException e) {

System.out.println("A SQL Exception. Boo Hiss.");

}

commandy3a at 2007-7-19 16:59:21 > top of Java-index,Other Topics,Algorithms...