Skip to content

Reading a File With a Classpath


The Issue

What if we need to open and read a file and we can't rely on the file path?

The Solution

We can read it from the Java classpath without knowing the file path. We already have been using this technique for the properties files. Now we're going to do this so we can read the file ourselves.

getResourceAsStream()

The method getResourceAsStream() will give us access to a file on the Java classpath. Here are the steps:

  1. Obtain a reference to a Class instance. We need that in order to call the getResourceAsStream().

    this.getClass()
    
  2. Determine the name of the file we want to read. This needs to be placed in a directory that is on Java's classpath. To access it there we need to add a slash to the name.

    "/file-name.txt"
    
  3. The getResourceAsStream() method returns an InputStream instance. Now we can put these together as the first line in this code.

    InputStream inputStream = this.getClass().getResourceAsStream("/file-name.txt");
    

InputStreamReader

In order to use BufferedReader and the helpful readLine() method, we need something with the type of Reader. The InputStream that we created above is not a Reader so we have to make one.

The InputStreamReader class has a constructor that takes an InputStream. This is how we use it:

    InputStreamReader inputStreamReader = new InputStreamReader(inputStream);

BufferedReader

Now we can make a BufferedReader. We know how to use this to read the lines in a file.

    BufferedReader searchTokensReader = new BufferedReader(inputStreamReader);

Exception Handling

We know we'll need a try/catch block. What exceptions will we need to catch? If we let the compiler tell us, and use the try-with-resources syntax, we'll get this as our full code.

    try (
        InputStream inputStream = this.getClass().getResourceAsStream("/file-name.txt");
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
        BufferedReader searchTokensReader = new BufferedReader(inputStreamReader)) {
        readSearchTokens(searchTokensReader);
    } catch (IOException inputOutputException) {
        inputOutputException.printStackTrace();
    } catch (Exception exception) {
        exception.printStackTrace();
    }

The readSearchTokens() method needs to read through the file in a loop. Note that each search token is on its own line. You will not use the split() in this analyzer.

The Search Tokens File Name

Where will our code get the name of the file that contains the search tokens? From the analyzer.properties file. Instead of a full filepath that we might expect, it will be something like this:

    classpath.search.tokens=/search-tokens.txt

The property key of classpath.search.tokens is required. The name of file is up to you.

Don't forget the /!!!

The file with the search tokens should be saved to the config/ directory. You need to have one search token per line and eliminate spaces in front of and after the tokens. You also need to filter out blank lines like you've done in the FileAnalysis class. Here's an example of how the file might look:

Georgiana
  Bartholomew
steeple

expressed
tombstone
Blacksmith
nothinghere