We at The Coders Lexicon thought it might be advantageous for some of you learning Java to learn how you might structure something like a basic random quote generator. To make things a little more interesting, what if we read the quotes from a file and used a “try-with-resources” statement? That way we could add additional quotes to it over time and have the program generate random quotes on demand. In this post we will show you one way to do this and explain all the steps. We will use an ArrayList to hold our quotes, java.util.Random to select a quote at random and a BufferedReader object to read from a file. Let’s jump in!
To start off, we are going to need some quotes file. Create a simple text file in your project and on each line setup a single quote. Remember where you put this file because you are going to need to know the path to that file to read it during program execution. In the code below, make sure to put that file path in the loadQuotes() function.
In Java SE 7+ a new statement was introduced called “try-with-resources”. This statement allows you to work with classes that implement the “java.lang.AutoCloseable” interface. The interface is used to make sure that any resources you use are automatically closed and cleaned up prior to the exit of the try-with-resources statement. It works very much like a traditional try-catch statement, however you will see that there is an expression in the “try” part. Since BufferedReader implements the AutoClosable interface, we can use it in a try-with-resources statement to make sure that the file is closed when the try-catch exits… even if there is an error!
Prior to Java SE 7, you could use a finally clause on your try-catch to do something similar. This is because the finally clause would execute no matter what happened in the try catch. However, a try-with-resources is a little bit cleaner and you should use it whenever you work with resources that implement the AutoClosable inteface to make sure you are always closing the resource when it is done.
import java.io.IOException; import java.util.ArrayList; import java.io.BufferedReader; import java.io.FileReader; import java.util.Random; public class Main { // List to hold our quotes we will load in static private ArrayList<String> listQuotes = new ArrayList<String>(0); public static void main(String[] args) { // First load the quotes into our list. loadQuotes(); // Next, generate a random integer based on the size of the quote list. Use the integer to then access a quote from the list. if (listQuotes.size() > 0) { Random r = new Random(); System.out.println(listQuotes.get(r.nextInt(listQuotes.size()))); } else { System.out.println("There are currently no quotes to read."); } } // This function simply loads quotes from our file. public static void loadQuotes() { // Here we have a try-with-resources setup that will automatically close BufferedReader try (BufferedReader bufReader = new BufferedReader(new FileReader("path_to_quotes.txt"))) { String line; // Read each line until we hit the end. Add each line to the list. while ((line = bufReader.readLine()) != null) { listQuotes.add(line); } } catch (IOException e) { System.out.println("Error loading quotes. Make sure the file is readable and exists."); } } }
As you can see from the code above, we start by setting up an ArrayList of strings to hold all of our quotes. You could use another listing data structure like a LinkedList or another form of list (I wouldn’t recommend an simple array however) but that is an implementation detail I will leave up to you.
After that, we start in main() where we call a function called loadQuotes(). In that function we use our try-with-resources statement to setup a BufferedReader to read a file. Remember that file we set up earlier? Here is where you are going to put in the path to that file. Notice how the BufferedReader (which we call bufReader here) is assigned right after the try keyword in parenthesis. After this line, we can work with the reader and when we exit the try-catch, the try-with-resources statement will make sure our BufferedReader is closed automatically! Notice I have no close() function call here. If an exception is thrown, we will print a simple error message. Again, even if there was an error, the BufferedReader is always closed.
Returning back to our main() function, we check if there are any quotes in our list. We do this by simply checking the length of the list. If there are some, we setup our random number generator to get a random number between 0 and the size of the list. Remember that nextInt() is going to exclude the number passed in. The fact that lists start at a zero index makes it so that if we pass in the total size of the list, it will pick numbers between 0 and the the size of the list – 1 (the last index of our list). Then we use the random index number to fetch the quote from the list using the “get” method of the ArrayList.
Once we have the selected random quote, all we have left is to print it and we are done.
In this short article we run through an example of using the try-with-resources statement, and a random number generator, to select a random quote from an ArrayList and display it. We showed how the code might work and quickly ran through an explanation. One of the reasons a program like this is good for learning is that the pattern of building up a list, randomly selecting one and managing our resources while doing it is a common pattern you will see in programming. Here we are working with strings, but we could have had a list of objects or varying lists of different sizes that a pattern like this would work well with.
We hope you enjoyed the code and learned something new about the try-with-resources statement. Thanks again for reading! 🙂