Java - Search for files in a directory
With **Java 8* there is an alternative that use streams and lambdas:
public static void recursiveFind(Path path, Consumer<Path> c) {
try (DirectoryStream<Path> newDirectoryStream = Files.newDirectoryStream(path)) {
StreamSupport.stream(newDirectoryStream.spliterator(), false)
.peek(p -> {
c.accept(p);
if (p.toFile()
.isDirectory()) {
recursiveFind(p, c);
}
})
.collect(Collectors.toList());
} catch (IOException e) {
e.printStackTrace();
}
}
So this will print all the files recursively:
recursiveFind(Paths.get("."), System.out::println);
And this will search for a file:
recursiveFind(Paths.get("."), p -> {
if (p.toFile().getName().toString().equals("src")) {
System.out.println(p);
}
});
Using Java 8+ features we can write the code in few lines:
protected static Collection<Path> find(String fileName, String searchDirectory) throws IOException {
try (Stream<Path> files = Files.walk(Paths.get(searchDirectory))) {
return files
.filter(f -> f.getFileName().toString().equals(fileName))
.collect(Collectors.toList());
}
}
Files.walk
returns a Stream<Path>
which is "walking the file tree rooted at" the given searchDirectory
. To select the desired files only a filter is applied on the Stream
files
. It compares the file name of a Path
with the given fileName
.
Note that the documentation of Files.walk
requires
This method must be used within a try-with-resources statement or similar control structure to ensure that the stream's open directories are closed promptly after the stream's operations have completed.
I'm using the try-resource-statement.
For advanced searches an alternative is to use a PathMatcher
:
protected static Collection<Path> find(String searchDirectory, PathMatcher matcher) throws IOException {
try (Stream<Path> files = Files.walk(Paths.get(searchDirectory))) {
return files
.filter(matcher::matches)
.collect(Collectors.toList());
}
}
An example how to use it to find a certain file:
public static void main(String[] args) throws IOException {
String searchDirectory = args[0];
String fileName = args[1];
PathMatcher matcher = FileSystems.getDefault().getPathMatcher("regex:.*" + fileName);
Collection<Path> find = find(searchDirectory, matcher);
System.out.println(find);
}
More about it: Oracle Finding Files tutorial
you can try something like this:
import java.io.*;
import java.util.*;
class FindFile
{
public void findFile(String name,File file)
{
File[] list = file.listFiles();
if(list!=null)
for (File fil : list)
{
if (fil.isDirectory())
{
findFile(name,fil);
}
else if (name.equalsIgnoreCase(fil.getName()))
{
System.out.println(fil.getParentFile());
}
}
}
public static void main(String[] args)
{
FindFile ff = new FindFile();
Scanner scan = new Scanner(System.in);
System.out.println("Enter the file to be searched.. " );
String name = scan.next();
System.out.println("Enter the directory where to search ");
String directory = scan.next();
ff.findFile(name,new File(directory));
}
}
Here is the output:
J:\Java\misc\load>java FindFile
Enter the file to be searched..
FindFile.java
Enter the directory where to search
j:\java\
FindFile.java Found in->j:\java\misc\load
This looks like a homework question, so I'll just give you a few pointers:
Try to give good distinctive variable names. Here you used "fileName" first for the directory, and then for the file. That is confusing, and won't help you solve the problem. Use different names for different things.
You're not using Scanner for anything, and it's not needed here, get rid of it.
Furthermore, the accept method should return a boolean value. Right now, you are trying to return a String. Boolean means that it should either return true or false. For example return a > 0;
may return true or false, depending on the value of a. But return fileName;
will just return the value of fileName, which is a String.