I need to load a bunch of words (about 70,000) from a text file, add it to a hashtable (using soundex as a key) and sort the values. While doing all these I want to show a progress bar using JProgressBar. Articles such as this and this, only gives a non-real example (a while loop). Can anyone suggest me how should I proceed. How can I get a number from above condition to set the value for the progress bar? Also it seems that there are different ways to do it - using thread, timer etc. Which could be the best method for the situation such as above?
+3
A:
I would read the text file in a loop on a dedicated work thread, not the event-dispatch thread (EDT). If I know the total number of words to be read, then I can compute the percentage completed at each iteration of the loop and update the progress bar accordingly.
Sample Code
The following code puts the progress bar in indeterminate mode during preprocessing and postprocessing, displaying an animation that indicates work is occurring. Determinate mode is used when reading iteratively from the input file.
// INITIALIZATION ON EDT
// JProgressBar progress = new JProgressBar();
// progress.setStringPainted(true);
// PREPROCESSING
// update progress bar (indeterminate mode)
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
progress.setIndeterminate(true);
progress.setString("Preprocessing...");
}
});
// perform preprocessing (open input file, determine total number of words, etc)
// PROCESSING
// update progress bar (switch to determinate mode)
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
progress.setIndeterminate(false);
}
});
int count = 0;
while (true)
{
// read a word from the input file; exit loop if EOF
// compute soundex representation
// add entry to map (hash table)
// compute percentage completed
count++;
final int percent = count * 100 / total;
// update progress bar on the EDT
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
progress.setString("Processing " + percent + "%");
progress.setValue(percent);
}
});
}
// POSTPROCESSING
// update progress bar (switch to indeterminate mode)
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
progress.setIndeterminate(true);
progress.setString("Postprocessing...");
}
});
// perform postprocessing (close input file, etc)
// DONE!
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
progress.setIndeterminate(false);
progress.setString("Done!");
progress.setValue(100);
}
});
Suggestions
- Consider writing a convenience method to update the progress bar on the EDT, so as to reduce clutter in your code (
SwingUtilities.invokeLater... public void run()...
)
Zach Scrivena
2008-11-10 04:18:32
Excellent work Zach! But I wonder if it will make my program way too slower.It seems that I've to process the input file twice -once to determine the no. of words and another time to process each word. Do you have any suggestions for that?Like holding all the words in an array or something like that
javac
2008-11-10 05:27:59
It depends where the bottleneck is... I imagine reading the file would be slower than computing the soundex representations and adding them to the map. (cont'd...)
Zach Scrivena
2008-11-10 05:44:19
(...cont'd) If so, I wouldn't want to read the file twice. Instead I would use the file length as the "total", and number of characters processed as the "count" (this, of course, is only an approximation because the file length is given in bytes, not characters).
Zach Scrivena
2008-11-10 05:45:18
@Zach: then use the number of bytes read instead of number of characters. Seeing a progress bar staying stuck on 100 (because you overflow and the bound model won't let you go over 100), or failing to reach 100 after the task has ended is a real "this was not written by a professional" smell.
Ran Biron
2008-11-10 10:19:25
@Ran: You raised a good point! Assuming that each character is represented by at least one byte, the processing may be completed before the progress bar reaches 100%. Like you said, we can count the bytes instead, but that would require more work (can't just use a simple FileReader).
Zach Scrivena
2008-11-10 10:36:45