Using following code as test, I got the hang of the issue. The main difference between walk* and list is that list(dir) gives a stream of files in the directory dir, while both walk* method walk the subtree of its argument including the root of subtree—the directory itself.
The difference between walk and walkFileTree is that they supply different interfaces for walking the tree: walkFileTree takes FileVisitor, walk gives Stream<Path>.
Copypublic class FilesTest {
public static void main(String[] args) {
final String pwd = System.getProperty("user.dir");
System.out.println("Working Directory = " + pwd);
Path dir = Paths.get(pwd);
System.out.println("Files.walk");
try (Stream<Path> stream = Files.walk(dir, 1)) {
stream.forEach(path -> FilesTest.doSomething("walk", path));
} catch (IOException e) {
logException("walk", e);
}
System.out.println("Files.walkFileTree");
try {
Files.walkFileTree(dir, Collections.emptySet(), 1, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
doSomething("visitFile", file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
logException("visitFile", exc);
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
logException("walkFileTree", e);
}
System.out.println("Files.list");
try (Stream<Path> stream = Files.list(dir)) {
stream.forEach(path -> FilesTest.doSomething("dir", path));
} catch (IOException e) {
logException("dir", e);
}
}
private static void logException(String title, IOException e) {
System.err.println(title + "\terror: " + e);
}
private static void doSomething(String title, Path file) {
System.out.println(title + "\t: " + file);
}
}
Answer from andrybak on Stack OverflowUsing following code as test, I got the hang of the issue. The main difference between walk* and list is that list(dir) gives a stream of files in the directory dir, while both walk* method walk the subtree of its argument including the root of subtree—the directory itself.
The difference between walk and walkFileTree is that they supply different interfaces for walking the tree: walkFileTree takes FileVisitor, walk gives Stream<Path>.
Copypublic class FilesTest {
public static void main(String[] args) {
final String pwd = System.getProperty("user.dir");
System.out.println("Working Directory = " + pwd);
Path dir = Paths.get(pwd);
System.out.println("Files.walk");
try (Stream<Path> stream = Files.walk(dir, 1)) {
stream.forEach(path -> FilesTest.doSomething("walk", path));
} catch (IOException e) {
logException("walk", e);
}
System.out.println("Files.walkFileTree");
try {
Files.walkFileTree(dir, Collections.emptySet(), 1, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
doSomething("visitFile", file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
logException("visitFile", exc);
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
logException("walkFileTree", e);
}
System.out.println("Files.list");
try (Stream<Path> stream = Files.list(dir)) {
stream.forEach(path -> FilesTest.doSomething("dir", path));
} catch (IOException e) {
logException("dir", e);
}
}
private static void logException(String title, IOException e) {
System.err.println(title + "\terror: " + e);
}
private static void doSomething(String title, Path file) {
System.out.println(title + "\t: " + file);
}
}
Files.list simply delegates to Files.newDirectoryStream and exposes the underlying java.nio.file.DirectoryStream as a java.util.stream.Stream, so their functionality is basically the same except that Files.newDirectoryStream allows you to pass an optional DirectoryStream.Filter.
Files.walkFileTree additionally exposes BasicFileAttributes (such as lastModifiedTime, isRegularFile, and size). If you are going to need these attributes, it could be more convenient (and possibly more efficient) to get them from Files.walkFileTree instead of looking them up separately.
I'm a little rusty in Java but here's a rough idea of where I think you're going:
import java.nio.files.*;
public class MyDirectoryInspector extends Object
{
public static void main(String[] args) {
Path startPath = Paths.get("\\CallGuidesTXT\\");
Files.walkFileTree(startPath, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException
{
String firstLine = Files.newBufferedReader(file, Charset.defaultCharset()).readLine();
System.out.println(firstLine);
return FileVisitResult.CONTINUE;
}
}); // <- you were missing a terminating ");"
}
}
That should walk through the directories and print the first line of each file to std out. I haven't touched Java since 1.6 so the JDK7 stuff is a little new to me too. I think you are getting confused as to what's a class and what's an interface. In my example we start with a basic class called MyDirectoryInspector to avoid confusion. It's enough to give us a program entry point, the main method where we start the inspection. The call to Files.walkFileTree takes 2 parameters, a start path and a file visitor which I have inlined. (I think the inlining can be confusing to some people if you're not used to this style.) This is a way of defining the actual class right in the place where you wish to use it. You could have also defined the SimpleFileVisitor separately and just instantiated it for your call as follows:
import java.nio.files.*;
public class MyDirectoryInspector extends Object
{
public static void main(String[] args) {
Path startPath = Paths.get("\\CallGuidesTXT\\");
Files.walkFileTree(startPath, new SimpleFileVisitor<Path>());
}
}
public class SimpleFileVisitor<Path>()) {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException
{
String firstLine = Files.newBufferedReader(file, Charset.defaultCharset()).readLine();
System.out.println(firstLine);
return FileVisitResult.CONTINUE;
}
}
It may make more sense, if you are just getting started, to keep things all separated. Define your classes without inlineing, take it one step at a time and make sure you understand each piece in isolation. My 2nd example gives you 2 individual pieces, a custom file visitor that can be used to print the 1st line of each file it visits and a program that uses it with the JDK Files class. Now let's look at another approach that omits the syntax:
import java.nio.files.*;
public class MyDirectoryInspector extends Object
{
public static void main(String[] args) {
Path startPath = Paths.get("\\CallGuidesTXT\\");
Files.walkFileTree(startPath, new SimpleFileVisitor());
}
}
public class SimpleFileVisitor()) {
@Override
public FileVisitResult visitFile(Object file, BasicFileAttributes attrs)
throws IOException
{
String firstLine = Files.newBufferedReader((Path)file, Charset.defaultCharset()).readLine();
System.out.println(firstLine);
return FileVisitResult.CONTINUE;
}
}
With the generics left off you have to declare file parameter as an Object type and cast it later when you choose to use it. In general, you don't want to replace an interface definition with a class definition or confuse the two as they are used for entirely different purposes.
Java interface can not have any implementations (ie code) - only method signatures.
Try changing interface to class:
public class FileVisitor<T> {
...