Both overloaded versions of
Files.walkFileTree
accept a starting point for the "walk" as an instance of the newly introduced Path class. Both of these methods also expect to be passed an instance of an implementation of the FileVisitor interface (SimpleFileVisitor in this case) of parameterized type Path
. My example in this post uses the simpler (and less flexible) of the two. It does not allow options such as following symbolic links to be specified. However, it works sufficiently for my example, demonstrates the technique nicely, and it is still easy enough to use the other version of the method with the options for a more flexible example.My simple example is a script written in Groovy that renames files. For simplicity's sake, I have hard-coded the root directory that will serve as the starting point of the walk, but this could have been easily retrieved as a command-line parameter to the script. This script renames files if they have spaces in their name and changes any uppercase letters to lowercase. The specific details of how files are renamed is documented as comments in the script itself. Here is that simple script.
renameFiles.groovy
#!/usr/bin/env groovy /** * renameFiles.groovy. * * For simplicity, this script assumes all files to be renamed are in the * directory C:\workarea. This script renames all files for which renaming is * allowed in the C:\workarea directory that meet certain characteristics. * This script replaces spaces in file names with underscores, trims spaces off * altogether (no underscore) that are the first or last characters of the file * name, and changes all letters in the file name to lowercase. */ import java.nio.file.attribute.BasicFileAttributes import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths import java.nio.file.FileVisitResult import java.nio.file.SimpleFileVisitor Path start = Paths.get("C:\\workarea") Files.walkFileTree(start, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path filePath, BasicFileAttributes attrs) throws IOException { def fileName = filePath.fileName def dirPath = filePath.parent def newFileName = fileName.toString().trim().toLowerCase().replace(" ","_") def newFilePath = Paths.get(dirPath.toString(), newFileName) Files.move(filePath, newFilePath) println "Renamed ${fileName} to ${newFileName}." return FileVisitResult.CONTINUE; } });
That's all there is to it! The output is captured in the screen snapshot that comes next. The snapshot shows a directory listing with the original files' names followed by a directory listing after this script has been run. The snapshot also includes the terminal in which this script was run.
As the example above indicates, I can override the method FileVisitor.visitFile to prescribe exactly what actions should be taken on each file that is encountered during my traversal of the files (walking the file tree) underneath the starting directory using Files.walkFileTree. The FileVisitor interface also advertises other hooks that I can implement to control other aspects of walking the file tree: visitFileFailed, preVisitDirectory, and postVisitDirectory.
There are other examples of walking the file tree with Java 7 available online. The Javadoc documentation for FileVisitor includes a "Usage Example" section that provides two more complicated examples than I've shown here. The first example shows deleting the contents of a directory first before deleting the directory itself and implements
visitFile
and postVisitDirectory
(delete the directory AFTER the contained files) in the process. The second example contained in that Javadoc implements preVisitDirectory
to first create a directory and then implements visitFile
to copy files to that target directory. The second example also shows off using of the other overloaded version of Files.walkFileTree
that accepts the option to follow symbolic links.The Java Tutorials now contain a section focusing exclusively on walking the file tree. Another interesting example online that is also an idea for another application of Java 7 NIO.2 features is in the post The ZIP filesystem provider in JDK7.
Finally, this is a big week for Java 7. Today is Oracle's Java 7 party. I'm looking forward to hearing what they have to say about Java 7 (includes coverage of file I/O). In addition, other recent posts of interest related to Java 7 include Using JDK 7's Fork/Join Framework and the announcement that build 147 is the first release candidate of Java 7.
Conclusion
This is a big week for Java 7. In this post, I've provided a quick taste of the power of the newly available file tree walking mechanism provided by Java 7's NIO.2 support.
1 comment:
All well and (VERY) good, but let's say we're searching for files that match a filename pattern and don't want to wait to see intermediate results on-screen (no output to console). Then (it seems like) SwingWorker needs to get involved. And that's where I am and that's where I am STUCK because doInBackground() is where (I believe you have to) publish() from and there's no loop within which to do so, if that's where the call to walkFileTree() should be placed. And if not, then surely doInBackground() would then need visitFile(), but there's no loop to be written. Any thoughts? (Consider http://stackoverflow.com/questions/20060366/swingworker-with-filevisitor-class-and-walkfiletree-which-iterates-internally)
Post a Comment