I'm writing spell checker program, which checks every word of some .txt file. it reads file while end of file is reached, and when it finds incorrect word it suggests correct variants in JList. and user chooses one and presses "next" button. Then it continues reading and searching for incorrect word.

while(all words in a file is not read)
{
check(word);//this returns array of suggestions
if("next" button is pressed)
{list.getSelectedWord() and continue while loop}
else {suspend loop until "next" button is pressed}

I assume you are doing something like writing a new version of the file with corrections made in it.

Try writing a checkFile() method which reads words and writes them to the output file. It does this until it hits a bad word at which point it returns a list of suggestions (or null if the end of file is reached). The point is that this method is over and done with once it hits the next bad word.

This method could be called in response to a "next" button click followed by using the returned values to populate some gui element displaying the suggestions.

Quite a different event handler would handle selection of an item. (eg by writing it to the output file and making the "next" button active again)

---------------------

Aside - some languages do implement iterators using a function that is effectively "paused" after it returns the next value.

pbrockway2, thanks. u hit the nail on the head. I'm doing the program you described. yes, I have checkFile() method and it returns list of suggestions. but that's where the problem occurs. I want to suspend the method until "next" is hit and continue working with this method, with while (or any other)loop in this method to be more precise. I don't see what do you mean "this method is over and done with once it hits the next bad word". do you mean that every time the button is hit, checkFile() starts reading file from the beginning???Isn't it expensive?

I don't see what do you mean "this method is over and done with once it hits the next bad word"

I meant that we have to accept up front that Java does not support "freezing" methods. Once the method returns, it returns and that's it.

do you mean that every time the button is hit, checkFile() starts reading file from the beginning?

Not at all. I imagine that somewhere in the model that represents the data there is a Reader instance. (some subclass of Reader).

The checkFile() method will have a loop which uses this reader to
* get the next word
* check it

* if good write it to the output file
* otherwise ceate and return the suggestion list

It does this over and over until it hits a bad word or end of file. The thing is that next time checkFile() is called that Reader instance will be in exactly the right place for the checking to pick up where it left off! There is no need for it start again from the beginning (and that wouldn't help because it wouldn't know where to start from...)

sorry, I didn't understand you. can you clarify use of Reader instance, how it will know where it left off?Here is piece of what I've done so far. I would appreciate if you associate your answer with this code
// this method supposed to return array, but as i have problem i left it void temporarily
public void reader() throws IOException
{
checker= new Checker();

String line;
String write;

while ((line = reader.readLine()) != null) {
StringTokenizer st = new StringTokenizer(line);
while(st.hasMoreTokens())
{
currentArray = checker.receiveList(st.nextToken());
// here is problem. how I return currentArray to populate with it GUI component and how to suspend it until user hits button
}

It's confusing to call the method reader() and also have a BufferedReader(?) called reader.

You cannot suspend the reader() method. Therefore it isn't a problem: it just can't be done. Rather, what remembers the state (where to read from) is the readervariable.

The procedure I outlined above would look in code something like the following:

Java Code:

import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
public class FileChecker {
private Reader in;
private Writer out;
public FileChecker(Reader in, Writer out) {
this.in = in;
this.out = out;
}
/**
* Copies words from in to out until it finds a misspelling.
* @return an array of suggestions for the misspelt word or null if EOF encountered
*/
public String[] doCheck() throws IOException {
// this is suitable for being called repeatedly in response to
// a "next" button click
while(true) {
String word = getWord();
if(word == null) {
return null;
}
String[] suggestions = getSuggestions(word);
if(suggestions == null) {
writeWord(word);
} else {
return suggestions;
}
}
}
/**
* Returns the next [i]word[/i] from the stream or null if there are no more characters.
* A word consists either entirely of non whitespace characters or entirely of
* whitespace characters.
*/
private String getWord() {
// insert magic along these lines...
// read in character by character accumulating the results which
// are returned once the end of the word is encountered.
// The reader in is used to get the characters. It will pick up each
// time from where it left off the last time this method was called.
// You have a bit of a problem implementing this method because
// you can't recognise the end of a word until you have read the
// first letter of the next word. Perhaps make in a PushbackReader?
// Or, better I think, have an instance variable set to the character
// which has been read but not yet returned to be written. (Such
// instance variables seem to be the way iterators are implemented.)
return null;
}
/**
* Returns an array of suggestions for incorrectly spelled words, or null if the
* word is OK or consists entirely of whitespace.
*/
private String[] getSuggestions(String word) {
// insert your magic here
return null;
}
/**
* Writes a word.
*/
public void writeWord(String word) throws IOException {
// this is suitable for being called in response to a suggestion
// being chosen in the gui
out.write(word);
}
}

Notice that the user of this class (the GUI?) will have to arrange things so that doCheck() is not called twice without an intervening writeWord(). Commonly this is done by having the click handler for the "next" button disable the button and the handler for the suggestion list handler reenable the button.

The GUI will have to also deal appropriately with the exceptions - the slings and arrows of outrageous I/O: hopefully with something better than a bare bodkin. And it will have to do the right thing once the EOF is detected.

can you clarify use of Reader instance, how it will know where it left off?

This is the key to seeing your way through the problem. I have no clue how a Reader instance does it, but you call reader.read(), reader.read(), reader.read() and it returns the characters in exactly the order they appear in the source.

Likewise if it goes reader.read() ... wait 5 minutes while the user chooses a correction ... reader.read() ... wait 5 more minutes ... reader.read(). The three characters returned will be in exactly the right order. It is the Reader instance's job to remember where it was last time. (Likewise for BufferedReader's readLine(), Scanner's nextLine() etc: It would be a bit silly if they didn't remember and returned the lines in any old order.)

while(all words in a file is not read)
{
check(word);//this returns array of suggestions
if("next" button is pressed)
{list.getSelectedWord() and continue while loop}
else {suspend loop until "next" button is pressed}

}

To suspend, I would probably call 'wait', and then the 'Next' button would issue a notify() to wake the loop up.

To suspend, I would probably call 'wait', and then the 'Next' button would issue a notify() to wake the loop up.

I'd use a SynchronousQueue<Command> where the Command is an interface that specifies what needs to be done. The while loop body tries to fetch the element from the queue and the buttons put a Command in the queue. If no element is available the while loop body waits (the queue takes care of that) and in no element is needed the buttons are disabled.

Using the classes in the java.util.concurrent package greatly simplify your code and the take away those wait(), notify() and syncing stuff from your code.

kind regards,

Jos

I have the stamina of a seal; I lie on the beach instead of running on it.

thank you for your time. seems like i really can't understand Readers concept of continuing from where it was last time, rather than starting everything again.

this is just some silly example, which reads only two lines of text

static String line;
public static void reader() throws FileNotFoundException, IOException{
BufferedReader reader = new BufferedReader(new FileReader("text.odt"));
int i=0;
while ((line = reader.readLine()) != null) {
if(i<3)
System.out.println(line);
i++;
}}
when you call it from another class like a.reader() it will return 1st and 2nd line of code, and if you call it again like b.reader() it will also return 1st and 2nd line, but not 3rd and 4th lines, as I understand you. therefore, it doesn't remember where it left off.

and why would you use character reader, but not line reader and then tokenize it in getWord() method?anyways that is not real problem

If you open a new FileReader on a file again and again those FileReaders will read the same file again and again. One FileReader doesn't know that another one has already read some bytes/characters from that one file.

kind regards,

Jos

I have the stamina of a seal; I lie on the beach instead of running on it.