Java nio, get all subfolders of some folder - java

How could I get all subfolders of some folder? I would use JDK 8 and nio.
picture
for example, for folder "Designs.ipj" method should return {"Workspace", "Library1"}
Thank you in advance!

List<Path> subfolder = Files.walk(folderPath, 1)
.filter(Files::isDirectory)
.collect(Collectors.toList());
it will contains folderPath and all subfolders in depth 1. If you need only subfolders, just add:
subfolders.remove(0);

You have to read all the items in a folder and filter out the directories, repeating this process as many times as needed.
To do this you could use listFiles()
File folder = new File("your/path");
Stack<File> stack = new Stack<File>();
Stack<File> folders = new Stack<File>();
stack.push(folder);
while(!stack.isEmpty())
{
File child = stack.pop();
File[] listFiles = child.listFiles();
folders.push(child);
for(File file : listFiles)
{
if(file.isDirectory())
{
stack.push(file);
}
}
}
see
Getting the filenames of all files in a folder
A simple recursive function would also work, just make sure to be wary of infinite loops.
However I am a bit more partial to DirectoryStream. It allows you to create a filter so that you only add the items that fit your specifications.
DirectoryStream.Filter<Path> visibleFilter = new DirectoryStream.Filter<Path>()
{
#Override
public boolean accept(Path file)
{
try
{
return Files.isDirectory(file));
}
catch(IOException e)
{
e.printStackTrace();
}
return false;
}
try(DirectoryStream<Path> stream = Files.newDirectoryStream(directory.toPath(), visibleFilter))
{
for(Path file : stream)
{
folders.push(child);
}
}

Related

How can I use file.listFiles() to list subdirectories and files also

I'm using file.listFile() to list the files and directories in a specified path. The reason I'm using file.ListFile() is because I'm using a FileFilter based on if the user only wants directories return or only files. But the result I have is that it only lists the folders and files in the path specified and not subfolders and files. This is what I'm working with right now:
file = new File(directory.getText().trim());
// Used this for testing; ListFiles() is a method
File[] test = ListFiles(directory.getName()); // I made up that will list the subfolders and files.
results.setListData(test); // Also for testing. results is a JList
// This is what i previously had that only lists folders and file in that directory
results.setListData(file.listFiles(new Filter() {
public boolean accept(File file) {
if (directories.isSelected()) {
// Directories checkBox
if (files.isSelected()) {
// Files checkBox
// FILES && DIRECTORIES
return (file.isDirectory() || file.isFile()) && (StringUtils.contains(file.getName(), userInput.getText().trim()));
}
// DIRECTORIES
return (file.isDirectory()) && (StringUtils.contains(file.getName(), userInput.getText().trim()));
} else {
if (files.isSelected()) {
// FILES
return (file.isFile()) && (StringUtils.contains(file.getName(), userInput.getText().trim()));
}
}
return true;
}
}));
}
I'm just not sure how to go about with the filters involved
The documentation for File#listFiles() does not state that it walks all subdirectories. So, you'll need to do that yourself. For each directory that is returned from listFiles(), you need to call recursively call listFiles() on it.
You could do this in the filter, as long as you're collecting all your files in another structure, since you cannot add more files to the result by using the filter alone. And I wouldn't recommend you do that.
You might be better off forgoing the filter and doing something like this:
List<File> files = new ArrayList<>();
public void getFiles(File file) {
for (File file : file.listFiles()) {
if (file.isDirectory()) {
if (collectDirectories) {
files.add(file);
}
getFiles(file);
} else {
if (collectFiles) {
files.add(file);
}
}
}
}
I found all the FileNameFilter stuff with subdirs a bit complex.
I use this now:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
<type>jar</type>
</dependency>
File inputDir = new File(inputPath.toString());
Iterator<File> matchesIterator = FileUtils.iterateFiles(
inputDir, new WildcardFileFilter("somefilenamefilter*.xml"), TrueFileFilter.TRUE);
while (matchesIterator.hasNext()) {
File someFile = matchesIterator .next();
...
}

Filtering files in a directory in Java

public class Sorter {
String dir1 = ("C:/Users/Drew/Desktop/test");
String dir2 = ("C:/Users/Drew/Desktop/");
public void SortingAlgo() throws IOException {
// Declare files for moving
File sourceDir = new File(dir1);
File destDir = new File(dir2);
//Get files, list them, grab only mp3 out of the pack, and sort
File[] listOfFiles = sourceDir.listFiles();
if(sourceDir.isDirectory()) {
for(int i = 0; i < listOfFiles.length; i++) {
//list Files
System.out.println(listOfFiles[i]);
String ext = FilenameUtils.getExtension(dir1);
System.out.println(ext);
}
}
}
}
I am trying to filter out only .mp3's in my program. I'm obviously a beginner and tried copying some things off of Google and this website. How can I set a directory (sourceDir) and move those filtered files to it's own folder?
File provides an ability to filter the file list as it's begin generated.
File[] listOfFiles = sourceDir.listFiles(new FileFilter() {
#Override
public boolean accept(File pathname) {
return pathname.getName().toLowerCase().endsWith(".mp3");
}
});
Now, this has a number of benefits, the chief among which is you don't need to post-process the list, again, or have two lists in memory at the same time.
It also provides pluggable capabilities. You could create a MP3FileFilter class for instance and re-use it.
I find the NIO.2 approach using GLOBs or custom filter the cleanest solution. Check out this example on how to use GLOB or filter example in the attached link:
Path directoryPath = Paths.get("C:", "Program Files/Java/jdk1.7.0_40/src/java/nio/file");
if (Files.isDirectory(directoryPath)) {
try (DirectoryStream<Path> stream = Files.newDirectoryStream(directoryPath, "*.mp3")) {
for (Path path : stream) {
System.out.println(path);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
For more information about content listing and directory filtering visit Listing and filtering directory contents in NIO.2
if(ext.endWith(".mp3")){
//do what ever you want
}

Delete all files in directory (but not directory) - one liner solution

I want to delete all files inside ABC directory.
When I tried with FileUtils.deleteDirectory(new File("C:/test/ABC/")); it also deletes folder ABC.
Is there a one liner solution where I can delete files inside directory but not directory?
import org.apache.commons.io.FileUtils;
FileUtils.cleanDirectory(directory);
There is this method available in the same file. This will also recursively deletes all sub-folders and files under them.
Docs: org.apache.commons.io.FileUtils.cleanDirectory
Do you mean like?
for(File file: dir.listFiles())
if (!file.isDirectory())
file.delete();
This will only delete files, not directories.
Peter Lawrey's answer is great because it is simple and not depending on anything special, and it's the way you should do it. If you need something that removes subdirectories and their contents as well, use recursion:
void purgeDirectory(File dir) {
for (File file: dir.listFiles()) {
if (file.isDirectory())
purgeDirectory(file);
file.delete();
}
}
To spare subdirectories and their contents (part of your question), modify as follows:
void purgeDirectoryButKeepSubDirectories(File dir) {
for (File file: dir.listFiles()) {
if (!file.isDirectory())
file.delete();
}
}
Or, since you wanted a one-line solution:
for (File file: dir.listFiles())
if (!file.isDirectory())
file.delete();
Using an external library for such a trivial task is not a good idea unless you need this library for something else anyway, in which case it is preferrable to use existing code. You appear to be using the Apache library anyway so use its FileUtils.cleanDirectory() method.
Java 8 Stream
This deletes only files from ABC (sub-directories are untouched):
Arrays.stream(new File("C:/test/ABC/").listFiles()).forEach(File::delete);
This deletes only files from ABC (and sub-directories):
Files.walk(Paths.get("C:/test/ABC/"))
.filter(Files::isRegularFile)
.map(Path::toFile)
.forEach(File::delete);
^ This version requires handling the IOException
Or to use this in Java 8:
try {
Files.newDirectoryStream( directory ).forEach( file -> {
try { Files.delete( file ); }
catch ( IOException e ) { throw new UncheckedIOException(e); }
} );
}
catch ( IOException e ) {
e.printStackTrace();
}
It's a pity the exception handling is so bulky, otherwise it would be a one-liner ...
public class DeleteFile {
public static void main(String[] args) {
String path="D:\test";
File file = new File(path);
File[] files = file.listFiles();
for (File f:files)
{if (f.isFile() && f.exists)
{ f.delete();
system.out.println("successfully deleted");
}else{
system.out.println("cant delete a file due to open or error");
} } }}
rm -rf was much more performant than FileUtils.cleanDirectory.
Not a one-liner solution but after extensive benchmarking, we found that using rm -rf was multiple times faster than using FileUtils.cleanDirectory.
Of course, if you have a small or simple directory, it won't matter but in our case we had multiple gigabytes and deeply nested sub directories where it would take over 10 minutes with FileUtils.cleanDirectory and only 1 minute with rm -rf.
Here's our rough Java implementation to do that:
// Delete directory given and all subdirectories and files (i.e. recursively).
//
static public boolean clearDirectory( File file ) throws IOException, InterruptedException {
if ( file.exists() ) {
String deleteCommand = "rm -rf " + file.getAbsolutePath();
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec( deleteCommand );
process.waitFor();
file.mkdirs(); // Since we only want to clear the directory and not delete it, we need to re-create the directory.
return true;
}
return false;
}
Worth trying if you're dealing with large or complex directories.
For deleting all files from directory say "C:\Example"
File file = new File("C:\\Example");
String[] myFiles;
if (file.isDirectory()) {
myFiles = file.list();
for (int i = 0; i < myFiles.length; i++) {
File myFile = new File(file, myFiles[i]);
myFile.delete();
}
}
Another Java 8 Stream solution to delete all the content of a folder, sub directories included, but not the folder itself.
Usage:
Path folder = Paths.get("/tmp/folder");
CleanFolder.clean(folder);
and the code:
public interface CleanFolder {
static void clean(Path folder) throws IOException {
Function<Path, Stream<Path>> walk = p -> {
try { return Files.walk(p);
} catch (IOException e) {
return Stream.empty();
}};
Consumer<Path> delete = p -> {
try {
Files.delete(p);
} catch (IOException e) {
}
};
Files.list(folder)
.flatMap(walk)
.sorted(Comparator.reverseOrder())
.forEach(delete);
}
}
The problem with every stream solution involving Files.walk or Files.delete is that these methods throws IOException which are a pain to handle in streams.
I tried to create a solution which is more concise as possible.
I think this will work (based on NonlinearFruit previous answer):
Files.walk(Paths.get("C:/test/ABC/"))
.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.filter(item -> !item.getPath().equals("C:/test/ABC/"))
.forEach(File::delete);
Cheers!
package com;
import java.io.File;
public class Delete {
public static void main(String[] args) {
String files;
File file = new File("D:\\del\\yc\\gh");
File[] listOfFiles = file.listFiles();
for (int i = 0; i < listOfFiles.length; i++)
{
if (listOfFiles[i].isFile())
{
files = listOfFiles[i].getName();
System.out.println(files);
if(!files.equalsIgnoreCase("Scan.pdf"))
{
boolean issuccess=new File(listOfFiles[i].toString()).delete();
System.err.println("Deletion Success "+issuccess);
}
}
}
}
}
If you want to delete all files remove
if(!files.equalsIgnoreCase("Scan.pdf"))
statement it will work.

Java to traverse all directories and find a file

I have to search for a file which can be in any directory or drive. It should be compatible with any operating system. When I googled, most of the code iterates through a particular directory but not full file system. Is there any way to do it efficiently ? Any help or suggestion will be really appreciated.
Below code where i got from http://www.mkyong.com/java/how-to-traverse-a-directory-structure-in-java/, but we have to pass some directory as parameter. Is there a way to generalize to get all the locations ?
public static void main (String args[]) {
displayIt(new File("C:\\"));
}
public static void displayIt(File node){
System.out.println(node.getAbsoluteFile());
if(node.isDirectory()){
String[] subNote = node.list();
for(String filename : subNote){
displayIt(new File(node, filename));
}
}
Apache Commons-IO is a good API for this kind of Operation. For Unix system you could just use root "/" however this will not do for windows, hence you will have to ask for all roots and iterate over them:
File[] roots = File.listRoots();
Collection<File> files = new ArrayList<File>();
for(File root : roots) {
files.addAll(FileUtils.listFiles(
root,
new RegexFileFilter(<your regex filter>),
DirectoryFileFilter.DIRECTORY
));
}
This sort of code snippet will list all the files in a directory and sub directories. You do not have to add any of the files to allFiles and you could do your check there. As you havent supplied any code yet (so I assume you havent tried anything) I'll let you update it ;)
private void addFiles(File file, Collection<File> allFiles) {
File[] files = file.listFiles();
if (files != null) {
for (File f : files) {
allFiles.add(f);
addFiles(f, allFiles);
}
}
}
if you want to do this by recursion, here is code for DFS, code might not working (i never test it), and it is not optimized, but it might give you some ideas how to solve your problem
File find(String directoryName, String pattern)
{
File currentDirectory = loadFile(directoryName);
for (String name: currentDirectory .list())
{
File children = loadFile(name)
if (children.isDirectory())
{
File file = find(name, pattern)
if (file !=null)
{
return file;
}
}
else
{
if (match(name,pattern)
{
return children;
}
}
}
return null;
}

Java: How to read directory folder, count and display no of files and copy to another folder?

I have to read a folder, count the number of files in the folder (can be of any type), display the number of files and then copy all the files to another folder (specified).
How would I proceed?
i Have to read a folder, count the number of files in the folder (can
be of any type) display the number of files
You can find all of this functionality in the javadocs for java.io.File
and then copy all the files to another folder (specified)
This is a bit more tricky. Read: Java Tutorial > Reading, Writing and Creating of Files
(note that the mechanisms described there are only available in Java 7 or later. If Java 7 is not an option, refer to one of many previous similar questions, e.g. this one: Fastest way to write to file? )
you have all the sample code here :
http://www.exampledepot.com
http://www.exampledepot.com/egs/java.io/GetFiles.html
File dir = new File("directoryName");
String[] children = dir.list();
if (children == null) {
// Either dir does not exist or is not a directory
} else {
for (int i=0; i<children.length; i++) {
// Get filename of file or directory
String filename = children[i];
}
}
// It is also possible to filter the list of returned files.
// This example does not return any files that start with `.'.
FilenameFilter filter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return !name.startsWith(".");
}
};
children = dir.list(filter);
// The list of files can also be retrieved as File objects
File[] files = dir.listFiles();
// This filter only returns directories
FileFilter fileFilter = new FileFilter() {
public boolean accept(File file) {
return file.isDirectory();
}
};
files = dir.listFiles(fileFilter);
The copying http://www.exampledepot.com/egs/java.io/CopyDir.html :
// Copies all files under srcDir to dstDir.
// If dstDir does not exist, it will be created.
public void copyDirectory(File srcDir, File dstDir) throws IOException {
if (srcDir.isDirectory()) {
if (!dstDir.exists()) {
dstDir.mkdir();
}
String[] children = srcDir.list();
for (int i=0; i<children.length; i++) {
copyDirectory(new File(srcDir, children[i]),
new File(dstDir, children[i]));
}
} else {
// This method is implemented in Copying a File
copyFile(srcDir, dstDir);
}
}
However is very easy to gooole for this stuff :)
I know this is too late but below code worked for me. It basically iterates through each file in directory, if found file is a directory then it makes recursive call. It only gives files count in a directory.
public static int noOfFilesInDirectory(File directory) {
int noOfFiles = 0;
for (File file : directory.listFiles()) {
if (file.isFile()) {
noOfFiles++;
}
if (file.isDirectory()) {
noOfFiles += noOfFilesInDirectory(file);
}
}
return noOfFiles;
}

Categories

Resources