8

I have to read a file containing a list of strings. I'm trying to follow the advice in this post. Both solutions require using FileUtils.readLines, but use a String, not a File as the parameter.

Set<String> lines = new HashSet<String>(FileUtils.readLines("foo.txt"));

I need a File.

This post would be my question, except the OP was dissuaded from using files entirely. I need a file if I want to use the Apache method, which is the my preferred solution to my initial problem.

My file is small (a hundred lines or so) and a singleton per program instance, so I do not need to worry about having another copy of the file in memory. Therefore I could use more basic methods to read the file, but so far it looks like FileUtils.readLines could be much cleaner. How do I go from resource to file.

Community
  • 1
  • 1
djechlin
  • 59,258
  • 35
  • 162
  • 290
  • 1
    If it is a classpath resource you should not be using the `File` type. Consider using Google's [Guava library](https://code.google.com/p/guava-libraries/) `Resources.readLines` method. – McDowell Aug 28 '13 at 21:33

3 Answers3

12

Apache Commons-IO has an IOUtils class as well as a FileUtils, which includes a readLines method similar to the one in FileUtils.

So you can use getResourceAsStream or getSystemResourceAsStream and pass the result of that to IOUtils.readLines to get a List<String> of the contents of your file:

List<String> myLines = IOUtils.readLines(ClassLoader.getSystemResourceAsStream("my_data_file.txt"));
matt
  • 78,533
  • 8
  • 163
  • 197
  • lol, so another question accepting an answer that bypasses the getting File problem. Java really doesn't like File apparently. – djechlin Aug 28 '13 at 23:25
  • Has nothing to do with it. File is not system agnostic, Stream is. – JoshDM Aug 29 '13 at 01:23
  • @djechlin a `File` is an actual file in the filesystem that has a path. Resources can be part of a jar file and you can't refer to just a part of a jar (or zip) through a path. What you can do is to get a stream to either a real file or a stream to a compressed file in an archive that also unzips on the fly. – zapl Aug 29 '13 at 10:47
2

I am assuming the file you want to read is a true resource on your classpath, and not simply some arbitrary file you could just access via new File("path_to_file");.

Try the following using ClassLoader, where resource is a String representation of the path to your resource file in your class path.

Valid String values for resource can include:

  • "foo.txt"
  • "com/company/bar.txt"
  • "com\\company\\bar.txt"
  • "\\com\\company\\bar.txt"

and path is not limited to com.company

Relevant code to get a File not in a JAR:

File file = null;

try {

    URL url = null;
    ClassLoader classLoader = {YourClass}.class.getClassLoader(); 

    if (classLoader != null) {

        url = classLoader.getResource(resource);
    }

    if (url == null) {

        url = ClassLoader.getSystemResource(resource);
    }

    if (url != null) {

        try {

            file = new File(url.toURI());

        } catch (URISyntaxException e) {

            file = new File(url.getPath());
        }
    }

} catch (Exception ex) { /* handle it */ }

// file may be null

Alternately, if your resource is in a JAR, you will have to use Class.getResourceAsStream(resource); and cycle through the file using a BufferedReader to simulate the call to readLines().

JoshDM
  • 4,939
  • 7
  • 43
  • 72
  • Should resource be the string, e.g. "`/com/mysite/app/file.txt"`? – djechlin Aug 28 '13 at 20:32
  • No, not with the preceding `/`. I've tested it on Windows 7 and updated with my successful test cases. Does not work with `.` as a path separator. – JoshDM Aug 28 '13 at 20:59
  • After reviewing http://stackoverflow.com/questions/676097/java-resource-as-file , one of the alternate answers there is similar, but not as wide in scope, as my answer. – JoshDM Aug 28 '13 at 21:04
  • 1
    Will `new File(url.toURI())` work for resources in JAR files? – millimoose Aug 28 '13 at 21:06
  • That was exactly what I was JUST going to update with; might have to use `getResourceAsStream()` and a `BufferedReader` in place of a call to `FileUtils`. – JoshDM Aug 28 '13 at 21:15
0

using a resource to read the file to a string:

String contents = 
 FileUtils.readFileToString(
  new File(this.getClass().getResource("/myfile.log").toURI()));

using inputstream:

List<String> listContents = 
 IOUtils.readLines(
  this.getClass().getResourceAsStream("/myfile.log"));
djechlin
  • 59,258
  • 35
  • 162
  • 290
Barry Knapp
  • 2,771
  • 2
  • 14
  • 9