Read Sub directory and specific files in Java - java

I need find all the java files in a directory
private void search(File directory) {
if (directory.isDirectory()) {
File[] javaFilesLs = directory.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(".java");
// return name.toLowerCase().endsWith(".java") || dir.isDirectory();
}
});
if (directory.canRead()) {
assert javaFilesLs != null;
for (File temp : javaFilesLs) {
if (temp.isDirectory()) {
search(temp);
} else {
fileList.add(temp.getAbsolutePath());
}
}
}
}
}
When I use the commented line it finds the subdirectory and all the files not only ".java" files.

The reason why you get all paths using the commented line, is that dir.isDirectory() will return true for all files.
Take a look at the documentation of FilenameFilter. It specifies that dir is "the directory in which the file was found."
So instead of looking at dir, you must test if name represents a directory. There may be smarter methods, but it can be done like this:
new File(dir.toPath().toString(), name).isDirectory() // returns true for directories
The whole snippet thus looks like this:
private void search(File directory) {
if (directory.isDirectory()) {
File[] javaFilesLs = directory.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(".java") || new File(dir.toPath().toString(), name).isDirectory();
}
});
if (directory.canRead()) {
assert javaFilesLs != null;
for (File temp : javaFilesLs) {
if (temp.isDirectory()) {
search(temp);
} else {
fileList.add(temp.getAbsolutePath());
}
}
}
}
}
Alternatively, Java 8 adds Files.walk which implements the recursion for you as a Stream.
private void search(File directory) throws IOException {
Files.walk(directory.toPath())
.filter(f -> {
return f.getFileName().toString().endsWith(".java");
})
.forEach(f -> fileList.add(f.toFile().getAbsolutePath()));
}

Related

Replace elseif with a more generic way

I have this piece of code:
#Override
public void inform(String data) {
if (data.equals(C.SubscriptionEvents.WINDOW_CLOSED)) {
File tempFolder = new File("temp");
File[] files = tempFolder.listFiles();
if (files != null) {
for (File f : files) f.delete();
}
} else if (data.equals(C.Controller.Commands.SELECT_MODE_VERTICES)) {
MainModel.setCurrentMode(Mode.VERTICES);
display.getInfoSection().repaint();
} else if (data.equals(C.Controller.Commands.SELECT_MODE_LINES)) {
MainModel.setCurrentMode(Mode.LINES);
display.getInfoSection().repaint();
} else if (data.equals(C.Controller.Commands.SELECT_MODE_SECTORS)) {
MainModel.setCurrentMode(Mode.SECTORS);
display.getInfoSection().repaint();
}
}
The method gets a string which is a Command name. According to the name, it does a specified behavior. As you can see, it starts to have too much elseifs (and probably will have more). This method belongs to an interface which is shared between packages so I decided to make the parameter as string.
Is there a better way to do it to avoid the method to be huge when there will be lots of commands (this includes switch case too)?
You can check Command pattern https://www.baeldung.com/java-command-pattern but it may require quite extensive refactoring and make method inform() accept objects of type Command
You could use an enum class, as follows:
public enum Command {
WINDOW_CLOSED { //C.SubscriptionEvents.WINDOW_CLOSED
public void invoke() {
File tempFolder = new File("temp");
File[] files = tempFolder.listFiles();
if (files != null) {
for (File f : files) f.delete();
}
}
}
,SELECT_MODE_VERTICES { // C.Controller.Commands.SELECT_MODE_VERTICES
public void invoke() {
MainModel.setCurrentMode(Mode.VERTICES);
display.getInfoSection().repaint();
}
}
,SELECT_MODE_LINES { // C.Controller.Commands.SELECT_MODE_LINES
public void invoke() {
MainModel.setCurrentMode(Mode.LINES);
display.getInfoSection().repaint();
}
}
,SELECT_MODE_SECTORS { // C.Controller.Commands.SELECT_MODE_SECTORS
public void invoke() {
MainModel.setCurrentMode(Mode.SECTORS);
display.getInfoSection().repaint();
}
}
;
public abstract void invoke();
}
Then replace the guts of your function above with this:
#Override
public void inform(String data) {
Command.valueOf(data).invoke();
}
The names of your 'enum' values must exactly match the string values of the various things you are testing for in your original code (e.g. C.SubscriptionEvents.WINDOW_CLOSED, C.SubscriptionEvents.WINDOW_CLOSED)
What about to use Enum instead of if...else?:
enum Event {
NULL(null, context -> { }),
WINDOWS_CLOSE(C.SubscriptionEvents.WINDOW_CLOSED, context -> {
File tempFolder = new File("temp");
File[] files = tempFolder.listFiles();
if (files != null) {
for (File f : files) f.delete();
}
}),
SELECT_MODE_VERTICES(C.Controller.Commands.SELECT_MODE_VERTICES, context -> {
MainModel.setCurrentMode(Mode.VERTICES);
display.getInfoSection().repaint();
}),
SELECT_MODE_LINES(C.Controller.Commands.SELECT_MODE_VERTICES, context -> {
MainModel.setCurrentMode(Mode.LINES);
display.getInfoSection().repaint();
}),
SELECT_MODE_SECTORS(C.Controller.Commands.SELECT_MODE_SECTORS, context -> {
MainModel.setCurrentMode(Mode.SECTORS);
display.getInfoSection().repaint();
});
private final String id;
private final Consumer<Foo> consumer;
Event(String id, Consumer<Foo> consumer) {
this.id = id;
this.consumer = consumer;
}
public final void accept(Foo context) {
consumer.accept(context);
}
public static Event selectEvent(String data) {
for (Event event : values())
if (event.id.equals(data))
return event;
return NULL;
}
}
And your code will be look like this one:
Event.selectEvent(data).accept(this);
You could simplify it this way...
#Override
public void inform(String data) {
Map<String, String> map = new HashMap<String, int>();
map.put(C.Controller.Commands.SELECT_MODE_VERTICES, Mode.VERTICES);
map.put(C.Controller.Commands.SELECT_MODE_LINES), Mode.LINES);
map.put(C.Controller.Commands.SELECT_MODE_SECTORS, Mode.SECTORS);
if (data.equals(C.SubscriptionEvents.WINDOW_CLOSED)) {
File tempFolder = new File("temp");
File[] files = tempFolder.listFiles();
if (files != null) {
for (File f : files) f.delete();
}
} else if (map.containsKey(data)) {
MainModel.setCurrentMode(map.get(key));
display.getInfoSection().repaint();
}
}

how to find all the files of given extension in whole harddisk [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
i have written a program that finds all the files of specified type by passing its extension.
my problem is, program is finding files in C drive only, but i want to search in for whole hard disk. here is my program sample
public class Find {
public static class Finder extends SimpleFileVisitor<Path> {
private final PathMatcher matcher;
private int numMatches = 0;
Finder(String pattern)
{
matcher = FileSystems.getDefault().getPathMatcher("glob:" + pattern);
}
// Compares the glob pattern against
// the file or directory name.
void find(Path file)
{
Path name = file.getFileName();
if (name != null && matcher.matches(name))
{
numMatches++;
System.out.println(file);
}
}
// Prints the total number of
// matches to standard out.
void done()
{
System.out.println("Matched: "+ numMatches);
}
// Invoke the pattern matching
// method on each file.
//#Override
public FileVisitResult visitFile(Path file,BasicFileAttributes attrs)
{
find(file);
return CONTINUE;
}
// Invoke the pattern matching
// method on each directory.
//#Override
public FileVisitResult preVisitDirectory(Path dir,BasicFileAttributes attrs)
{
find(dir);
return CONTINUE;
}
//#Override
public FileVisitResult visitFileFailed(Path file,IOException exc)
{
System.err.println(exc);
return CONTINUE;
}
}
static void usage()
{
System.err.println("java Find <path>" +" -name \"<glob_pattern>\"");
System.exit(-1);
}
public static void main(String[] args)throws IOException
{
if (args.length < 2 )
{
usage();
}
Path startingDir = Paths.get(args[0]);
String pattern = args[1];
Finder finder = new Finder(pattern);
Files.walkFileTree(startingDir, finder);
finder.done();
}
}
You can use the File.listRoots() method to find all drives on Windows. After that just do an independent search on each drive.
Using the new API (java.nio.file) there's another way: FileSystem.getDefault().getRootDirectories().
for (Path startingDir : FileSystem.getDefault().getRootDirectories()) {
// find files here
}
Try something like this
File folder = new File("D:\\DestFile");
File[] listOfFiles = folder.listFiles();
for (File file : listOfFiles) {
if (file.isFile()&& (file.getName().substring(file.getName().lastIndexOf('.')+1).equals("your_type"))) {// txt or docx or something
// do something
}
}
Try this. you can read all file in your PC by this
public static void main(String[] args) {
File[] paths = File.listRoots();
for(File directory:paths){
getFile(directory.toString());
}
}
public static void getFile(String directoryName) {
File directory = new File(directoryName);
File[] fList = directory.listFiles();
if(fList!=null){
for (File file : fList) {
if (file.isFile()) {
System.out.println(file.toString());
} else if (file.isDirectory()) {
getFile(file.getAbsolutePath());
}
}
}
}

Filtering and selecting files from a directory

I have an application right now that selects files from a directory. what I want to do is be able to have a feature where you can put in a file extension such as .gif, .txt etc.. and after a button is clicked the application will run through the directory and find and select all files of that type. The only code I have to show is of my current application which has none of this. Was hoping for a point in the right direction or some advice.
private List<File> getMatchingFiles(File parent, final String extension) {
File[] files = parent.listFiles(new FileFilter() {
public boolean accept(File dir) {
String name = dir.getName();
if(name.endsWith(extension)) {
return true;
}
}
});
List<File> retval = Arrays.asList( files );
return retval;
}
For use in a JFileChooser, all the answers so far offered are sub-optimal. Instead implement JFileChooser.setFileFilter(javax.swing.filechooser.FileFilter) for the best user experience.
It might end up looking something like this1:
Image obtained using code courtesy of A Sample FileChooser Program.
What you are looking for is probably the java.io.File#list(filter).
edit: If you want the entire file system be searched, then you need to recursively scan every direcotry:
public static void filter (String dirname, List<File> result) {
try {
for (String f : new File(dirname).list()) {
String filename = dirname + f;
File theFile = new File(filename);
if (theFile.isDirectory()) {
filter(filename + "/", result);
} else if (new FileFilter() {
public boolean accept(File pathname) {
return pathname.getName().endsWith(".gif");
}
}.accept(theFile)) {
result.add(theFile);
}
}
} catch (Exception e) {
// may raise null-pointer when access denied
}
}
public static void main(String[] args) {
List<File> result = new ArrayList<File>();
filter("F:/", result);
System.out.println(result.size());
}
FilenameFilter filter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return (!name.endsWith(".gif")
}
};

Recursively list files in Java

How do I recursively list all files under a directory in Java? Does the framework provide any utility?
I saw a lot of hacky implementations. But none from the framework or nio
Java 8 provides a nice stream to process all files in a tree.
try (Stream<Path> stream = Files.walk(Paths.get(path))) {
stream.filter(Files::isRegularFile)
.forEach(System.out::println);
}
This provides a natural way to traverse files. Since it's a stream you can do all nice stream operations on the result such as limit, grouping, mapping, exit early etc.
UPDATE: I might point out there is also Files.find which takes a BiPredicate that could be more efficient if you need to check file attributes.
Files.find(Paths.get(path),
Integer.MAX_VALUE,
(filePath, fileAttr) -> fileAttr.isRegularFile())
.forEach(System.out::println);
Note that while the JavaDoc eludes that this method could be more efficient than Files.walk it is effectively identical, the difference in performance can be observed if you are also retrieving file attributes within your filter. In the end, if you need to filter on attributes use Files.find, otherwise use Files.walk, mostly because there are overloads and it's more convenient.
TESTS: As requested I've provided a performance comparison of many of the answers. Check out the Github project which contains results and a test case.
FileUtils have iterateFiles and listFiles methods. Give them a try. (from commons-io)
Edit: You can check here for a benchmark of different approaches. It seems that the commons-io approach is slow, so pick some of the faster ones from here (if it matters)
// Ready to run
import java.io.File;
public class Filewalker {
public void walk( String path ) {
File root = new File( path );
File[] list = root.listFiles();
if (list == null) return;
for ( File f : list ) {
if ( f.isDirectory() ) {
walk( f.getAbsolutePath() );
System.out.println( "Dir:" + f.getAbsoluteFile() );
}
else {
System.out.println( "File:" + f.getAbsoluteFile() );
}
}
}
public static void main(String[] args) {
Filewalker fw = new Filewalker();
fw.walk("c:\\" );
}
}
Java 7 will have has Files.walkFileTree:
If you provide a starting point and a file visitor, it will invoke various methods on the file visitor as it walks through the file in the file tree. We expect people to use this if they are developing a recursive copy, a recursive move, a recursive delete, or a recursive operation that sets permissions or performs another operation on each of the files.
There is now an entire Oracle tutorial on this question.
No external libraries needed.
Returns a Collection so you can do whatever you want with it after the call.
public static Collection<File> listFileTree(File dir) {
Set<File> fileTree = new HashSet<File>();
if(dir==null||dir.listFiles()==null){
return fileTree;
}
for (File entry : dir.listFiles()) {
if (entry.isFile()) fileTree.add(entry);
else fileTree.addAll(listFileTree(entry));
}
return fileTree;
}
I would go with something like:
public void list(File file) {
System.out.println(file.getName());
File[] children = file.listFiles();
for (File child : children) {
list(child);
}
}
The System.out.println is just there to indicate to do something with the file. there is no need to differentiate between files and directories, since a normal file will simply have zero children.
I prefer using a queue over recursion for this kind of simple traversion:
List<File> allFiles = new ArrayList<File>();
Queue<File> dirs = new LinkedList<File>();
dirs.add(new File("/start/dir/"));
while (!dirs.isEmpty()) {
for (File f : dirs.poll().listFiles()) {
if (f.isDirectory()) {
dirs.add(f);
} else if (f.isFile()) {
allFiles.add(f);
}
}
}
just write it yourself using simple recursion:
public List<File> addFiles(List<File> files, File dir)
{
if (files == null)
files = new LinkedList<File>();
if (!dir.isDirectory())
{
files.add(dir);
return files;
}
for (File file : dir.listFiles())
addFiles(files, file);
return files;
}
With Java 7 you can use the following class:
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
public class MyFileIterator extends SimpleFileVisitor<Path>
{
public MyFileIterator(String path) throws Exception
{
Files.walkFileTree(Paths.get(path), this);
}
#Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attributes) throws IOException
{
System.out.println("File: " + file);
return FileVisitResult.CONTINUE;
}
#Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attributes) throws IOException
{
System.out.println("Dir: " + dir);
return FileVisitResult.CONTINUE;
}
}
This code is ready to run
public static void main(String... args) {
File[] files = new File("D:/").listFiles();
if (files != null)
getFiles(files);
}
public static void getFiles(File[] files) {
for (File file : files) {
if (file.isDirectory()) {
getFiles(file.listFiles());
} else {
System.out.println("File: " + file);
}
}
}
I think this should do the work:
File dir = new File(dirname);
String[] files = dir.list();
This way you have files and dirs. Now use recursion and do the same for dirs (File class has isDirectory() method).
In Java 8, we can now use the Files utility to walk a file tree. Very simple.
Files.walk(root.toPath())
.filter(path -> !Files.isDirectory(path))
.forEach(path -> System.out.println(path));
Apart from the recursive traversal one can use a Visitor based approach as well.
Below code is uses Visitor based approach for the traversal.It is expected that the input to the program is the root directory to traverse.
public interface Visitor {
void visit(DirElement d);
void visit(FileElement f);
}
public abstract class Element {
protected File rootPath;
abstract void accept(Visitor v);
#Override
public String toString() {
return rootPath.getAbsolutePath();
}
}
public class FileElement extends Element {
FileElement(final String path) {
rootPath = new File(path);
}
#Override
void accept(final Visitor v) {
v.visit(this);
}
}
public class DirElement extends Element implements Iterable<Element> {
private final List<Element> elemList;
DirElement(final String path) {
elemList = new ArrayList<Element>();
rootPath = new File(path);
for (File f : rootPath.listFiles()) {
if (f.isDirectory()) {
elemList.add(new DirElement(f.getAbsolutePath()));
} else if (f.isFile()) {
elemList.add(new FileElement(f.getAbsolutePath()));
}
}
}
#Override
void accept(final Visitor v) {
v.visit(this);
}
public Iterator<Element> iterator() {
return elemList.iterator();
}
}
public class ElementWalker {
private final String rootDir;
ElementWalker(final String dir) {
rootDir = dir;
}
private void traverse() {
Element d = new DirElement(rootDir);
d.accept(new Walker());
}
public static void main(final String[] args) {
ElementWalker t = new ElementWalker("C:\\temp");
t.traverse();
}
private class Walker implements Visitor {
public void visit(final DirElement d) {
System.out.println(d);
for(Element e:d) {
e.accept(this);
}
}
public void visit(final FileElement f) {
System.out.println(f);
}
}
}
You can use below code to get a list of files of specific folder or directory recursively.
public static void main(String args[]) {
recusiveList("D:");
}
public static void recursiveList(String path) {
File f = new File(path);
File[] fl = f.listFiles();
for (int i = 0; i < fl.length; i++) {
if (fl[i].isDirectory() && !fl[i].isHidden()) {
System.out.println(fl[i].getAbsolutePath());
recusiveList(fl[i].getAbsolutePath());
} else {
System.out.println(fl[i].getName());
}
}
}
I came up with this for printing all the files/file names recursively.
private static void printAllFiles(String filePath,File folder) {
if(filePath==null) {
return;
}
File[] files = folder.listFiles();
for(File element : files) {
if(element.isDirectory()) {
printAllFiles(filePath,element);
} else {
System.out.println(" FileName "+ element.getName());
}
}
}
Lists all files with provided extensions,with option to scan
subfolders (recursive)
public static ArrayList<File> listFileTree(File dir,boolean recursive) {
if (null == dir || !dir.isDirectory()) {
return new ArrayList<>();
}
final Set<File> fileTree = new HashSet<File>();
FileFilter fileFilter = new FileFilter() {
private final String[] acceptedExtensions = new String[]{"jpg", "png", "webp", "jpeg"};
#Override
public boolean accept(File file) {
if (file.isDirectory()) {
return true;
}
for (String extension : acceptedExtensions) {
if (file.getName().toLowerCase().endsWith(extension)) {
return true;
}
}
return false;
}
};
File[] listed = dir.listFiles(fileFilter);
if(listed!=null){
for (File entry : listed) {
if (entry.isFile()) {
fileTree.add(entry);
} else if(recursive){
fileTree.addAll(listFileTree(entry,true));
}
}
}
return new ArrayList<>(fileTree);
}
List<Path> filePaths = Files
.find(Paths.get(dir), Integer.MAX_VALUE, (filePath, fileAttr) -> fileAttr.isRegularFile() || fileAttr.isDirectory())
.collect(Collectors.toList());
filePaths will have files and folder list which can be iterated and proceed further.
Non-recursive BFS with a single list (particular example is searching for *.eml files):
final FileFilter filter = new FileFilter() {
#Override
public boolean accept(File file) {
return file.isDirectory() || file.getName().endsWith(".eml");
}
};
// BFS recursive search
List<File> queue = new LinkedList<File>();
queue.addAll(Arrays.asList(dir.listFiles(filter)));
for (ListIterator<File> itr = queue.listIterator(); itr.hasNext();) {
File file = itr.next();
if (file.isDirectory()) {
itr.remove();
for (File f: file.listFiles(filter)) itr.add(f);
}
}
My version (of course I could have used the built in walk in Java 8 ;-) ):
public static List<File> findFilesIn(File rootDir, Predicate<File> predicate) {
ArrayList<File> collected = new ArrayList<>();
walk(rootDir, predicate, collected);
return collected;
}
private static void walk(File dir, Predicate<File> filterFunction, List<File> collected) {
Stream.of(listOnlyWhenDirectory(dir))
.forEach(file -> walk(file, filterFunction, addAndReturn(collected, file, filterFunction)));
}
private static File[] listOnlyWhenDirectory(File dir) {
return dir.isDirectory() ? dir.listFiles() : new File[]{};
}
private static List<File> addAndReturn(List<File> files, File toAdd, Predicate<File> filterFunction) {
if (filterFunction.test(toAdd)) {
files.add(toAdd);
}
return files;
}
Here a simple but perfectly working solution using recursion:
public static List<Path> listFiles(String rootDirectory)
{
List<Path> files = new ArrayList<>();
listFiles(rootDirectory, files);
return files;
}
private static void listFiles(String path, List<Path> collectedFiles)
{
File root = new File(path);
File[] files = root.listFiles();
if (files == null)
{
return;
}
for (File file : files)
{
if (file.isDirectory())
{
listFiles(file.getAbsolutePath(), collectedFiles);
} else
{
collectedFiles.add(file.toPath());
}
}
}
private void fillFilesRecursively(File file, List<File> resultFiles) {
if (file.isFile()) {
resultFiles.add(file);
} else {
for (File child : file.listFiles()) {
fillFilesRecursively(child, resultFiles);
}
}
}
Kotlin has FileTreeWalk for this purpose. For example:
dataDir.walkTopDown().filter { !it.isDirectory }.joinToString("\n") {
"${it.toRelativeString(dataDir)}: ${it.length()}"
}
Will produce a text list of all the non-directory files under a given root, one file per line with the path relative to the root and length.
The accepted answer is great, however it breaks down when you want to do IO inside the lambda.
Here is what you can do if your action declares IOExceptions.
You can treat the filtered stream as an Iterable, and then do your action in a regular for-each loop. This way, you don't have to handle exceptions inside a lambda.
try (Stream<Path> pathStream = Files.walk(Paths.get(path))
.filter(Files::isRegularFile)) {
for (Path file : (Iterable<Path>) pathStream::iterator) {
// something that throws IOException
Files.copy(file, System.out);
}
}
Found that trick here: https://stackoverflow.com/a/32668807/1207791
Another way you can do even if someone already provide Java 8 walk.
This one will provide you all files recursively
private Stream<File> files(File file) {
return file.isDirectory()
? Arrays.stream(file.listFiles()).flatMap(this::files)
: Stream.of(file);
}
public static String getExten(String path) {
int i = path.lastIndexOf('.');
if (i > 0) {
return path.substring(i);
}
else return "";
}
public static List<String> GetAllFiles(String path, List<String>fileList){
File file = new File(path);
File[] files = file.listFiles();
for(File folder:files) {
if(extensions.contains(getExten(folder.getPath()))) {
fileList.add(folder.getPath());
}
}
File[] direcs = file.listFiles(File::isDirectory);
for(File dir:direcs) {
GetAllFiles(dir.getPath(),fileList);
}
return fileList;
}
This is a simple recursive function that should give you all the files. extensions is a list of string that contains only those extensions which are accepted. Example extensions = [".txt",".docx"] etc.
The accepted answer is poor because it can result in a resource leak.
Files.walk is backed by DirectoryStreams.
The returned stream encapsulates one or more DirectoryStreams. If timely disposal of file system resources is required, the try-with-resources construct should be used to ensure that the stream's close method is invoked after the stream operations are completed. Operating on a closed stream will result in an IllegalStateException.
A DirectoryStream must be closed as specified in it's javadoc:
A DirectoryStream is opened upon creation and is closed by invoking the close method. Closing a directory stream releases any resources associated with the stream. Failure to close the stream may result in a resource leak. The try-with-resources statement provides a useful construct to ensure that the stream is closed:
Path dir = ...
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
for (Path entry: stream) {
...
}
}
As a result, the true answer is:
try (Stream<Path> stream = Files.walk(Paths.get(path))) {
// Do something with the stream.
stream.filter(Files::isRegularFile)
.forEach(System.out::println);
}
Example outputs *.csv files in directory recursive searching Subdirectories using Files.find() from java.nio:
String path = "C:/Daten/ibiss/ferret/";
logger.debug("Path:" + path);
try (Stream<Path> fileList = Files.find(Paths.get(path), Integer.MAX_VALUE,
(filePath, fileAttr) -> fileAttr.isRegularFile() && filePath.toString().endsWith("csv"))) {
List<String> someThingNew = fileList.sorted().map(String::valueOf).collect(Collectors.toList());
for (String t : someThingNew) {
t.toString();
logger.debug("Filename:" + t);
}
}
Posting this example, as I had trouble understanding howto pass the filename parameter in the #1 example given by Bryan, using foreach on Stream-result -
Hope this helps.
base on #Michael answer, add check whether listFiles return null
static Stream<File> files(File file) {
return file.isDirectory()
? Optional.ofNullable(file.listFiles()).map(Stream::of).orElseGet(Stream::empty).flatMap(MainActivity::files)
: Stream.of(file);
}
or use Lightweight-Stream-API, which support Android5 & Android6
static Stream<File> files(File f) {
return f.isDirectory() ? Stream.ofNullable(f.listFiles()).flatMap(MainActivity::files) : Stream.of(f);
}
Based on stacker answer. Here is a solution working in JSP without any external libraries so you can put it almost anywhere on your server:
<!DOCTYPE html>
<%# page session="false" %>
<%# page import="java.util.*" %>
<%# page import="java.io.*" %>
<%# page contentType="text/html; charset=UTF-8" %>
<%!
public List<String> files = new ArrayList<String>();
/**
Fills files array with all sub-files.
*/
public void walk( File root ) {
File[] list = root.listFiles();
if (list == null) return;
for ( File f : list ) {
if ( f.isDirectory() ) {
walk( f );
}
else {
files.add(f.getAbsolutePath());
}
}
}
%>
<%
files.clear();
File jsp = new File(request.getRealPath(request.getServletPath()));
File dir = jsp.getParentFile();
walk(dir);
String prefixPath = dir.getAbsolutePath() + "/";
%>
Then you just do something like:
<ul>
<% for (String file : files) { %>
<% if (file.matches(".+\\.(apk|ipa|mobileprovision)")) { %>
<li><%=file.replace(prefixPath, "")%></li>
<% } %>
<% } %>
</ul>
import java.io.File;
public class Main {
public static void main(String[] args) {
loopFiles(new File("C:\\Users\\serge.klimkovitch\\Documents"));
}
private static void loopFiles(File element) {
if (element.isDirectory()) {
for (File currentFile : element.listFiles()) {
loopFiles(currentFile);
System.out.println(currentFile);
}
}
}
}

How to scan a folder in Java?

How can I get list all the files within a folder recursively in Java?
Not sure how you want to represent the tree? Anyway here's an example which scans the entire subtree using recursion. Files and directories are treated alike. Note that File.listFiles() returns null for non-directories.
public static void main(String[] args) {
Collection<File> all = new ArrayList<File>();
addTree(new File("."), all);
System.out.println(all);
}
static void addTree(File file, Collection<File> all) {
File[] children = file.listFiles();
if (children != null) {
for (File child : children) {
all.add(child);
addTree(child, all);
}
}
}
Java 7 offers a couple of improvements. For example, DirectoryStream provides one result at a time - the caller no longer has to wait for all I/O operations to complete before acting. This allows incremental GUI updates, early cancellation, etc.
static void addTree(Path directory, Collection<Path> all)
throws IOException {
try (DirectoryStream<Path> ds = Files.newDirectoryStream(directory)) {
for (Path child : ds) {
all.add(child);
if (Files.isDirectory(child)) {
addTree(child, all);
}
}
}
}
Note that the dreaded null return value has been replaced by IOException.
Java 7 also offers a tree walker:
static void addTree(Path directory, final Collection<Path> all)
throws IOException {
Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
#Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
all.add(file);
return FileVisitResult.CONTINUE;
}
});
}
import java.io.File;
public class Test {
public static void main( String [] args ) {
File actual = new File(".");
for( File f : actual.listFiles()){
System.out.println( f.getName() );
}
}
}
It displays indistinctly files and folders.
See the methods in File class to order them or avoid directory print etc.
http://java.sun.com/javase/6/docs/api/java/io/File.html
You can also use the FileFilter interface to filter out what you want. It is best used when you create an anonymous class that implements it:
import java.io.File;
import java.io.FileFilter;
public class ListFiles {
public File[] findDirectories(File root) {
return root.listFiles(new FileFilter() {
public boolean accept(File f) {
return f.isDirectory();
}});
}
public File[] findFiles(File root) {
return root.listFiles(new FileFilter() {
public boolean accept(File f) {
return f.isFile();
}});
}
}
public static void directory(File dir) {
File[] files = dir.listFiles();
for (File file : files) {
System.out.println(file.getAbsolutePath());
if (file.listFiles() != null)
directory(file);
}
}
Here dir is Directory to be scanned. e.g. c:\
Visualizing the tree structure was the most convenient way for me :
public static void main(String[] args) throws IOException {
printTree(0, new File("START/FROM/DIR"));
}
static void printTree(int depth, File file) throws IOException {
StringBuilder indent = new StringBuilder();
String name = file.getName();
for (int i = 0; i < depth; i++) {
indent.append(".");
}
//Pretty print for directories
if (file.isDirectory()) {
System.out.println(indent.toString() + "|");
if(isPrintName(name)){
System.out.println(indent.toString() + "*" + file.getName() + "*");
}
}
//Print file name
else if(isPrintName(name)) {
System.out.println(indent.toString() + file.getName());
}
//Recurse children
if (file.isDirectory()) {
File[] files = file.listFiles();
for (int i = 0; i < files.length; i++){
printTree(depth + 4, files[i]);
}
}
}
//Exclude some file names
static boolean isPrintName(String name){
if (name.charAt(0) == '.') {
return false;
}
if (name.contains("svn")) {
return false;
}
//.
//. Some more exclusions
//.
return true;
}
In JDK7, "more NIO features" should have methods to apply the visitor pattern over a file tree or just the immediate contents of a directory - no need to find all the files in a potentially huge directory before iterating over them.

Categories