1

I was writing some java code that lists the files in a subdirectory on the Classpath as a stream.

InputStream is = YourClazz.class.getClassLoader().getResourceAsStream("subdirectory/")

This returns an InputStream which I then convert into a String.

String fileNames = "";
try (final Scanner scanner = new Scanner(is).useDelimiter("\\A")) {
    fileNames = scanner.hasNext() ? scanner.next() : "";
}

I then used System.getProperty("line.seperator") to read the lines and be platform independent.

for (String fileName : fileNames.split(System.getProperty("line.separator"))) {
    // todo
}

But it failed on Windows as the delimiter in fileNames is \n and not line.separator. Is this because of the Scanner? I got this one-liner from Read/convert an InputStream to a String

Update based on answers below, I am using this code now, which works on Windows and Linux:

InputStream in = YourClazz.class.getClassLoader().getResourceAsStream("subdirectory/")
try (final Scanner scanner = new Scanner(in)) {
    while (scanner.hasNextLine()) {
        final String fileName = scanner.nextLine();
        // todo
    }
}
Community
  • 1
  • 1
reikje
  • 2,474
  • 2
  • 19
  • 35

3 Answers3

1

Don't handle splitting lines manually. Let Scanner do it for you.

List<String> lines = new ArrayList<>();
try (final Scanner scanner = new Scanner(is)) {
    while(scanner.hasNextLine()){
        lines.add(scanner.nextLine());
        //or handle that line here instead of storing it in list
    }
}
Pshemo
  • 113,402
  • 22
  • 170
  • 242
  • I am on Java 7 sorry. Can you elaborate why I cannot know which line separator is used? The InputStream is created using: `YourClazz.class.getClassLoader().getResourceAsStream("subdirectory/")`. In other words is a listing of files in a directory - it's not a physical file sitting on my harddisk. – reikje Jul 30 '15 at 12:48
  • Sorry, I misread your question. I though you ware reading text file, not directory. – Pshemo Jul 30 '15 at 13:00
1

getResourceAsStream() is best understood as a short-hand for getResource().openStream(), in other words, what it provides when attempting to access a directory, is completely unspecified and left to the particular URL protocol handler. E.g. if the context is a Jar file, looking up directories usually fails. If the context is an http resource, attempting to get a directory may yield the contents of an index.html. Some protocols, e.g. ftp, may invariably use a / as separator, others may use the system’s file separator.

The only fail safe way is not to try to lookup a directory but a file resource, and then use an API which abstracts from the result and allows to resolve paths relative to the result and to list directories. Such an API exists since Java 7:

URI clURI = Object.class.getResource("Object.class").toURI();
if(!clURI.getScheme().equals("file")) try {
    FileSystems.getFileSystem(clURI);
} catch(FileSystemNotFoundException ex) {
    FileSystems.newFileSystem(clURI, Collections.<String,Object>emptyMap());
}
for(Path p: Files.newDirectoryStream(Paths.get(clURI).getParent())) {
  System.out.println(p.toUri());
}

This will list all (virtual) files located in the same package as java.lang.Object, usually a jar resource for which URL based lookups for a directory fail. It works similarly for other class location. Note that it doesn’t rely on a particular separator at all.

Holger
  • 243,335
  • 30
  • 362
  • 661
0

You will need to use:

 Path path = Paths.get(fileName);
 String[] files = fileName.split(path.getFileSystem().getSeparator());

Edit: My bad I got this question wrongly. This will get file separator not line separator as you needed.

ap0calypt1c
  • 471
  • 4
  • 10
  • Doesn't work. For instance on the `MacOSXFileSystem` the value of `getSeparator()` is `/` but an example value of `fileNames` above looks like `ns_test1.json\nns_test2.json\n` – reikje Jul 30 '15 at 12:37