Streaming files and moving them after read
You can chain a close action to a stream, which will be executed automatically in case of flatMap
:
Stream.generate(localFileProvider::getNextFile).takeWhile(Objects::nonNull)
.flatMap(file -> {
try {
Path p = file.toPath();
return Files.lines(p, Charset.defaultCharset()).onClose(() -> {
try { // move path/x/y/z to path/x/y/z.moved
Files.move(p, p.resolveSibling(p.getFileName()+".moved"));
} catch(IOException ex) { throw new UncheckedIOException(ex); }
});
} catch(IOException ex) { throw new UncheckedIOException(ex); }
})
.forEach(System.out::println);
It’s important that the documentation of onClose
states:
Close handlers are run when the
close()
method is called on the stream, and are executed in the order they were added.
So the moving close handler is executed after the already existing close handler that will close the file handle used for reading the lines.
I used Charset.defaultCharset()
to mimic the behavior of the nested constructors new InputStreamReader(new FileInputStream(file)))
of your question’s code, but generally, you should use a fixed charset, like the Files.lines
’s default UTF-8 whenever possible.
I would just create two methods:
public void processFile(File f);
public void moveFile(File f, File dstFolder);
then in lambda:
Stream.generate(localFileProvider::getNextFile).forEach(file->
{
processFile(file);
moveFile(file, dstFolder);
}
);
Actually it will be very easy if you can divide the logic into different method
public Path readFile(File eachFile) {
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
//try-with-resources
try (Stream<String> lines = reader.lines()) {
lines.forEach(System.out::println);
}
catch (IOException e) {
e.printStackTrace();
}
return eachFile.toPath();
}
And then call this method for each file
(1) Stream.generate(localFileProvider::getNextFile)
(2) .map(this::readFile) //process each file
(3) .forEach(path->Files.move(path,Paths.get("new path"))); //then move each file