Peter Penzov
Peter Penzov

Reputation: 1648

Get content of a file inside a directory

I want to get the content of a file inside a directory:

/sys/block/sda/device/model

I use this code to get the content:

String content = new String(Files.readAllBytes(Paths.get("/sys/block/sda/device/model")));

But in some scenarios, I have cases like this:

/sys/block/sda/device/model
/sys/block/sdb/device/model
/sys/block/sdc/device/model

How I can iterate all the directories starting with

sd* and print the file model?

Can you show me some example for Java 8 with filter?

Upvotes: 0

Views: 302

Answers (2)

Holger
Holger

Reputation: 298103

Here is an example of how to do this using Java 8 features:

Function<Path,byte[]> uncheckedRead = p -> {
  try { return Files.readAllBytes(p); }
  catch(IOException ex) { throw new UncheckedIOException(ex); }
};
try(Stream<Path> s=Files.find(Paths.get("/sys/block"), 1,
    (p,a)->p.getName(p.getNameCount()-1).toString().startsWith("sd"))) {
  s.map(p->p.resolve("device/model")).map(uncheckedRead).map(String::new)
   .forEach(System.out::println);
}

This is an example that strives for compactness and working stand-alone. For real applications, it’s likely that you would do it a bit differently. The task of using an IO operation as a Function which doesn’t allow checked exception is quite common so you might have a wrapper function like:

interface IOFunction<T,R> {
    R apply(T in) throws IOException;
}
static <T,R> Function<T,R> wrap(IOFunction<T,R> f) {
    return t-> { try { return f.apply(t); }
      catch(IOException ex) { throw new UncheckedIOException(ex); }
    };
}

Then you can use

try(Stream<Path> s=Files.find(Paths.get("/sys/block"), 1,
    (p,a)->p.getName(p.getNameCount()-1).toString().startsWith("sd"))) {
  s.map(p->p.resolve("device/model")).map(wrap(Files::readAllBytes))
   .map(String::new).forEach(System.out::println);
}

But maybe you’d use newDirectoryStream instead even if the returned DirectoryStream is not a Stream and hence requires a manual Stream creation as this method allows passing a glob pattern like "sd*":

try(DirectoryStream<Path> ds
                     =Files.newDirectoryStream(Paths.get("/sys/block"), "sd*")) {
  StreamSupport.stream(ds.spliterator(), false)
    .map(p->p.resolve("device/model")).map(wrap(Files::readAllBytes))
    .map(String::new).forEach(System.out::println);
}

Finally, the option to process the files as stream of lines should be mentioned:

try(DirectoryStream<Path> ds
                     =Files.newDirectoryStream(Paths.get("/sys/block"), "sd*")) {
  StreamSupport.stream(ds.spliterator(), false)
    .map(p->p.resolve("device/model")).flatMap(wrap(Files::lines))
    .forEach(System.out::println);
}

Upvotes: 2

prashant thakre
prashant thakre

Reputation: 5147

Rather using st* it's better if you can first search the existing folder inside the path /sys/block by using below code.

Please find working example :-

String dirNames[] = new File("E://block").list();
for(String name : dirNames)
{
    if (new File("E://block//" + name).isDirectory())
    {
        if(name.contains("sd")){
            String content = new String(Files.readAllBytes(Paths.get("E://block//"+name+"//device//model")));
            System.out.println(content);
        }

    }
}

Upvotes: 1

Related Questions