Java Jar file: How to read a file from a Jar file

Java JAR file FAQ: Can you show me how a Java application can read a text file from own of its own JAR files?

Solution

Here's an example of some Java code I'm using to read a file (a text file) from a Java JAR file. This is useful any time you pack files and other resources into JAR files to distribute your Java application.

How to read a Java Jar file, example #1

The source code to read a file from a Java JAR file uses the getClass and getResourceAsStream methods:

  public void test3Columns()
  throws IOException
  {
    InputStream is = getClass().getResourceAsStream("3Columns.csv");
    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader br = new BufferedReader(isr);
    String line;
    while ((line = br.readLine()) != null) 
    {
      CSVLineTokenizer tok = new CSVLineTokenizer(line);
      assertEquals("Should be three columns in each row",3,tok.countTokens());
    }
    br.close();
    isr.close();
    is.close();
  }

The trick to reading text files from JAR files are these lines of code, especially the first line:

InputStream is = getClass().getResourceAsStream("3Columns.csv");
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);

In my example I have a plain text file named "3Columns.csv" in the same directory as the class that contains this method. Without a path stated before the filename (like "/foo/bar/3Columns.csv") the getResourceAsStream method looks for this text file in its current directory.

Note that I'm doing all of this within the context of a JUnit test method. Also note that I'm throwing any exceptions that occur rather than handling them. I don't recommend this for real world programming, but it works okay for my unit testing needs today.

I haven't read through the Javadocs yet to know if all of those close statements at the end are necessary. I'll try to get back to that later.

Java: How to read a Jar file, example #2

Here is a slightly more simple version of that method:

public String readFromJARFile(String filename)
throws IOException
{
  InputStream is = getClass().getResourceAsStream(filename);
  InputStreamReader isr = new InputStreamReader(is);
  BufferedReader br = new BufferedReader(isr);
  StringBuffer sb = new StringBuffer();
  String line;
  while ((line = br.readLine()) != null) 
  {
    sb.append(line);
  }
  br.close();
  isr.close();
  is.close();
  return sb.toString();
}

In this sample I've eliminated the CSVLineTokenizer and replaced it with a simple StringBuffer, and I return a plain old String at the end of the method.

Also, if I didn't stress it properly earlier, with this approach the resource file that you're trying to read from must be in the same directory in the jar file as this class. This is inferred by the getClass().getResourceAsStream() method call, but I don't think I really stressed that enough earlier.

Also, I haven't looked at it in a while, but I think you can just call the is.close() method to close all your resources, you don't have to make all the close calls I make here, but I'm not 100% positive.

Reading a file from a jar file as a File

Here's one more example of how to do this, this time using some code from a current Scala project:

val file = new File(getClass.getResource("zipcode_data.csv").toURI)

Although the code shown is Scala, I think you can see that you can use this approach to read the file as a java.io.File instead of reading it as a stream.

One more Java "read from Jar file" example

While I'm working on another Java project, I just ran across another example of how to read a file from a Java jar file in this method:

private void playSound(String soundfileName)
{
  try
  {
    ClassLoader CLDR = this.getClass().getClassLoader();
    InputStream inputStream = CLDR.getResourceAsStream("com/devdaily/desktopcurtain/sounds/" + soundfileName);
    AudioStream audioStream = new AudioStream(inputStream);
    AudioPlayer.player.start(audioStream);
  }
  catch (Exception e)
  {
    // log this
  }
}

As you can guess from looking at this code, this example shows how to read a resource file from a jar file in a java application, and in this approach, the resource file that I'm reading doesn't have to be in the same directory as the Java class file. As you can imagine, this is a much more flexible approach.