patternjavaMinor
Prompt system from reading a text file
Viewed 0 times
readingfilesystemtextfromprompt
Problem
I worked starting from basic example code from an exercise in chapter 10 of Java: A Beginner's Guide, Sixth Edition, the code in the exercise was not very good and I wanted to improve upon it and make it my own, so this is what I came up with.
This reads the content of a text file, displays and reads titles/subjects, which lines are preceded by the
I realize it's probably not very good, and I'm looking to improve my handling of I/O in general, please critique it thoroughly.
```
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* Help System using a text file as source.
*/
public class HelpSystem {
private char titleLineMarker;
private final String STOP_WORD = "stop";
private final String HELP_SYSTEM_FILE_PATH = "C:/git/JavaExercises/src/chapter10/HelpSystem.txt";
/**
* Default constructor assumes character '#' is assumed to be the
* line marker for titles/headers, according to standard Markdown syntax.
*/
public HelpSystem() {
titleLineMarker = '#';
run();
}
/**
* Alternate constructor with different line marker.
* @param titleLineMarker the marker character that marks a line as subtitle.
*/
public HelpSystem(char titleLineMarker) {
this.titleLineMarker = titleLineMarker;
run();
}
/**
* Run the HelpSystem app.
*/
private void run() {
String topic;
System.out.printf("Try the help system. Enter \"%s\" to end.", STOP_WORD);
readTopics();
do {
topic = getSelection();
if (!isStop(topic)) {
if (!helpOn(topic)) {
System.out.printf("Topic not found: %s%n", topic);
}
}
} while(!isStop(topic));
}
/**
* Reads
This reads the content of a text file, displays and reads titles/subjects, which lines are preceded by the
# character, gets text input from the console, and displays information from searching the text file again for the user-input search.I realize it's probably not very good, and I'm looking to improve my handling of I/O in general, please critique it thoroughly.
```
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* Help System using a text file as source.
*/
public class HelpSystem {
private char titleLineMarker;
private final String STOP_WORD = "stop";
private final String HELP_SYSTEM_FILE_PATH = "C:/git/JavaExercises/src/chapter10/HelpSystem.txt";
/**
* Default constructor assumes character '#' is assumed to be the
* line marker for titles/headers, according to standard Markdown syntax.
*/
public HelpSystem() {
titleLineMarker = '#';
run();
}
/**
* Alternate constructor with different line marker.
* @param titleLineMarker the marker character that marks a line as subtitle.
*/
public HelpSystem(char titleLineMarker) {
this.titleLineMarker = titleLineMarker;
run();
}
/**
* Run the HelpSystem app.
*/
private void run() {
String topic;
System.out.printf("Try the help system. Enter \"%s\" to end.", STOP_WORD);
readTopics();
do {
topic = getSelection();
if (!isStop(topic)) {
if (!helpOn(topic)) {
System.out.printf("Topic not found: %s%n", topic);
}
}
} while(!isStop(topic));
}
/**
* Reads
Solution
Interface
I don't think that instantiating a
-
Instantiate, then run the loop separately
-
A static method
It would be better for the no-argument constructor to chain to
Note that anytime you have a special character, you should probably also have a mechanism for allowing that character to be treated literally. See RFC 821 Section 4.5.2 for an example of such an escaping mechanism.
Better yet, avoid inventing your own format, and use a standard format like xml or yaml for which a parser already exists.
Printing the stack trace is not a very good way of handling an
Parsing
Two of the private methods parse the help file. Assuming that the file is small, it should be better parse it into a data structure just once at the beginning.
… both because it keeps the lines shorter and because it would close the
Run loop
Your
I don't think that instantiating a
HelpSystem should have a side-effect of starting the interpreter loop. Either of these following designs would be better:-
Instantiate, then run the loop separately
HelpSystem help = new HelpSystem();
help.run();-
A static method
HelpSystem.run();It would be better for the no-argument constructor to chain to
this('#'); instead of setting titleLineMarker itself. But why should the marker be configurable at all? Just settle on the file format an stick to it.Note that anytime you have a special character, you should probably also have a mechanism for allowing that character to be treated literally. See RFC 821 Section 4.5.2 for an example of such an escaping mechanism.
Better yet, avoid inventing your own format, and use a standard format like xml or yaml for which a parser already exists.
Printing the stack trace is not a very good way of handling an
IOException. Such an exception should be considered fatal, not a situation to spew some text and try to continue. If you don't know what to do with an exception, just declare throws IOException to propagate it.Parsing
Two of the private methods parse the help file. Assuming that the file is small, it should be better parse it into a data structure just once at the beginning.
try(BufferedReader topicReader = new BufferedReader((new FileReader(HELP_SYSTEM_FILE_PATH)))) has an extra pair of parentheses. It would be better written astry (FileReader fr = new FileReader(HELP_SYSTEM_FILE_PATH);
BufferedReader topicReader = new BufferedReader(fr);) {
…
}… both because it keeps the lines shorter and because it would close the
FileReader properly if the FileReader constructor throws an exception.Run loop
Your
run() loop should be better structured to avoid the redundant isStop() checks.private void run() {
// readTopics(); <-- Perhaps better done in the constructor
System.out.printf("Try the help system. Enter \"%s\" to end.", STOP_WORD);
for (String topic; !isStop(topic = getSelection()); ) {
if (!helpOn(topic)) {
System.out.printf("Topic not found: %s%n", topic);
}
}
}Code Snippets
HelpSystem help = new HelpSystem();
help.run();HelpSystem.run();try (FileReader fr = new FileReader(HELP_SYSTEM_FILE_PATH);
BufferedReader topicReader = new BufferedReader(fr);) {
…
}private void run() {
// readTopics(); <-- Perhaps better done in the constructor
System.out.printf("Try the help system. Enter \"%s\" to end.", STOP_WORD);
for (String topic; !isStop(topic = getSelection()); ) {
if (!helpOn(topic)) {
System.out.printf("Topic not found: %s%n", topic);
}
}
}Context
StackExchange Code Review Q#125520, answer score: 4
Revisions (0)
No revisions yet.