Iterate through all files in Java - java

I want to make my program print huge list of all files that I have on my computer. My problem is that it only prints files from first folder of the first hard-drive, when I want it to print all files located on my computer. Any ideas what am I doing wrong here? Thanks.
Here is code I use:
Main:
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
ArrayList<File> roots = new ArrayList();
roots.addAll(Arrays.asList(File.listRoots()));
for (File file : roots) {
new Searcher(file.toString().replace('\\', '/')).search();
}
}
}
and Searcher class:
import java.io.File;
public class Searcher {
private String root;
public Searcher(String root) {
this.root = root;
}
public void search() {
System.out.println(root);
File folder = new File(root);
File[] listOfFiles = folder.listFiles();
for (File file : listOfFiles) {
String path = file.getPath().replace('\\', '/');
System.out.println(path);
if (!path.contains(".")) {
new Searcher(path + "/").search();
}
}
}
}

I just tried this and it worked for me. I did have to add one null check and changed the directory evaluation method though:
package test;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
public class Searcher {
public static void main(String[] args) {
ArrayList<File> roots = new ArrayList<File>();
roots.addAll(Arrays.asList(File.listRoots()));
for (File file : roots) {
new Searcher(file.toString().replace('\\', '/')).search();
}
}
private String root;
public Searcher(String root) {
this.root = root;
}
public void search() {
System.out.println(root);
File folder = new File(root);
File[] listOfFiles = folder.listFiles();
if(listOfFiles == null) return; // Added condition check
for (File file : listOfFiles) {
String path = file.getPath().replace('\\', '/');
System.out.println(path);
if (file.isDirectory()) {
new Searcher(path + "/").search();
}
}
}
}

You should update your search method like this:
public void search() {
System.out.println(root);
File folder = new File(root);
File[] listOfFiles = folder.listFiles();
for (File file : listOfFiles) {
String path = file.getPath().replace('\\', '/');
System.out.println(path);
if (file.isDirectory()) {
new Searcher(path + "/").search();
}
}
}

If Java 7 is an option, look into the walkFileTree() method. It will allow you to visit all files and directories in a tree, which you can start from the root of your drive. Just implement a basic FileVisitor to process the file attributes for each Path. You can get started here.

If you're using Java SE 7, use the new file API:
http://docs.oracle.com/javase/7/docs/api/java/nio/file/FileVisitor.html
http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#walkFileTree%28java.nio.file.Path,%20java.util.Set,%20int,%20java.nio.file.FileVisitor%29
http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#walkFileTree%28java.nio.file.Path,%20java.nio.file.FileVisitor%29

I don't know what error you are getting but I got a NPE because you are not checking for the null after the following line.
File[] listOfFiles = folder.listFiles();
After changing the code as follows it seemed to run fine , I stopped it because I have a lot of files. I am assuming it will go on to the next root after the first root(c:/ in my case)
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
public class Search {
public static void main(String[] args) {
ArrayList<File> roots = new ArrayList();
roots.addAll(Arrays.asList(File.listRoots()));
for (File file : roots) {
System.out.println(file.toString());
new Searcher(file.toString().replace('\\', '/')).search();
}
}
}
class Searcher {
private String root;
public Searcher(String root) {
this.root = root;
}
public void search() {
System.out.println(root);
File folder = new File(root);
File[] listOfFiles = folder.listFiles();
if(listOfFiles!=null)
{
for (File file : listOfFiles) {
String path = file.getPath().replace('\\', '/');
System.out.println(path);
if (!path.contains(".")) {
new Searcher(path + "/").search();
}
}
}
}
}

Related

How find files in a directory knowing a part of the name

I have a problem, i have this directory with 1k+ files and some folders. I need find the path of the files(which are in subdirectories) that starts with "BCM", but not only the first i find but every single file which start with that.
I tried looking at other answers about this topic but i couldn't find help,
tried using this code:
File dir = new File("K:\\Jgencs");
FilenameFilter filter = new FilenameFilter()
{
public boolean accept (File dir, String name)
{
return name.startsWith("BCM");
}
};
String[] children = dir.list(filter);
if (children == null)
{
System.out.println("No directory found");
}
else
{
for (int i = 0; i< children.length; i++)
{
String filename = children[i];
System.out.println(filename);
File h = new File(dir,filename);
System.out.println(h.getAbsolutePath()
[UPDATED] This is how you can achieve using plain Java and filter text from a variable passing as parameter:
Here is my directory: /tmp
And here is the code running:
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class GetAllFilesInDirectory {
public static void main(String[] args) throws IOException {
String filter = "BCM";
List<File> files = listFiles("/tmp", new CustomerFileFilter(filter));
for (File file : files) {
System.out.println("file: " + file.getCanonicalPath());
}
}
private static List<File> listFiles(String directoryName, CustomerFileFilter fileFilter) {
File directory = new File(directoryName);
List<File> files = new ArrayList<>();
// Get all files from a directory.
File[] fList = directory.listFiles(fileFilter);
if(fList != null) {
for (File file : fList) {
if (file.isFile()) {
files.add(file);
} else if (file.isDirectory()) {
files.addAll(listFiles(file.getAbsolutePath(), fileFilter));
}
}
}
return files;
}
}
class CustomerFileFilter implements FileFilter {
private final String filterStartingWith;
public CustomerFileFilter(String filterStartingWith) {
this.filterStartingWith = filterStartingWith;
}
#Override
public boolean accept(File file) {
return file.isDirectory() || file.isFile() && file.getName().startsWith(filterStartingWith);
}
}
This is the output:
file: /private/tmp/BCM01.txt
file: /private/tmp/BCM01
file: /private/tmp/subfolder1/BCM02.txt
Doing recursive calls to the method when finding a directory to also list the files form inside, and filtering by name the files before adding.
You want Files.walk:
try (Stream<Path> files = Files.walk(Paths.get("K:\\Jgencs"))) {
files.filter(f -> f.getFileName().toString().startsWith("BCM")).forEach(
file -> System.out.println(file));
}

Java - get files names from directory

I have an issue with a Java code where the directory names are being pulled along with the file names. I want to modify the following code to pull only files and not sub-directories from the given directory. I'm a Java newbie so it would be greatly appreciated if someone could answer with the modified code. I have tried a lot of things from past stack overflow answers and just couldn't get it to compile.
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "DirectoryList" as import java.io.*;
import java.sql.*;
public class DirectoryList
{
public static void getList(String directory) throws SQLException
{
File path = new File(directory);
String[] list = path.list();
String element;
for(int i = 0; i < list.length; i++)
{
element = list[i];
#sql {
call Load_File_List_p(:element, :directory)
};
}
}
}
/
Here is what I already tried:
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "DirectoryList" as import java.io.*;
import java.sql.*;
public class DirectoryList
{
public static void getList(File directory) throws SQLException
{
File path = new File(directory);
File[] listOfFiles = path.listFiles();
for (File file : listOfFiles)
{
if (file.isFile())
{
for(int i = 0; i < listOfFiles.length; i++)
{
file = listOfFiles[i];
#sql {
call Load_File_List_p(:file, :directory)
};
}
}
}
}
}
/
Thanks!
Only problem with your code is position of extra for loop iteration. Please look below code :
import java.io.*;
import java.sql.*;
public class DirectoryList
{
public static void getList(File directory) throws SQLException {
File path = new File(directory);
File[] listOfFiles = path.listFiles();
for (File file : listOfFiles)
{
if (file.isFile())
{
#sql {
call Load_File_List_p(:file, :directory)
};
}
}
}
}
You have some SQL stuff in there that I removed as the question was about file listings, not SQL. You were pretty close though. Your inner for loop trips you up and needed to be tossed, that was about it. You looped for each file, then for each file you looped again on that file so each file got processed multiple times.
The calls I used have two possible exceptions, so I just put those in the method signature.
public void getList() throws SecurityException, NullPointerException
{
File path = new File("DirectoryName");
File[] listOfFiles = path.listFiles();
if (listOfFiles == null) {
System.out.println("There was an error.");
}
for (File file : listOfFiles)
{
if (file.isFile())
{
System.out.println(file.getName());
}
}
}
The listFiles() method has an overload that takes a FileFilter for your convenience. Combined with lambda, we have:
File [] files = path.listFiles(File::isFile);
if (files != null) {
// listFiles may return null if path is not a directory or there's an IO issue.
for (File f : files) {
// do sth
}
}
Java 8 solution Get all files from current directory:
File path = new File(directory);
File[] list = path.listFiles();
List<File> files = Arrays.stream(list).filter(t->t.isFile()).collect(Collectors.toList());
Get all files including the subfolders:
public static List<File> getList(File directory)
{
File[] list = directory.listFiles();
final List<File> files = Arrays.stream(list).filter(t->t.isFile()).collect(Collectors.toList());
List<File> directories = Arrays.stream(list).filter(t->!t.isFile()).collect(Collectors.toList());
directories.stream().forEach(t->files.addAll(getList(t)));
return files;
}

How to search files recursively (my custom code)?

I would like to search for files recursively. According to other solutions, I have already done a big portion of the code:
public static File[] getFiles(String path) {
File file = new File(path);
// Get the subdirectories.
String[] directories = file.list(new FilenameFilter() {
#Override
public boolean accept(File current, String name) {
return new File(current, name).isDirectory();
}
});
for (String dir : directories) {
// Doing recursion
}
// Get the files inside the directory.
FileFilter fileFilter = new FileFilter();
File[] files = file.listFiles(fileFilter);
return files;
}
FileFilter is just a custom filter of mine. My problem is that I don't know how to do the recursion in this case. Of course I could call getFiles() again for each subdirectory with the subdirectory path as argument but somehow the returning File array must be merged.
Does somebody have a solution?
Use the find() method.
/* Your filter can be initialized however you need... */
YourCustomFilter filter = new YourCustomFilter(extension, maxSize);
try (Stream<Path> s = Files.find(dir, Integer.MAX_VALUE, filter::test)) {
return s.map(Path::toFile).toArray(File[]::new);
}
This assumes your custom filter has a method called test() that accepts the file and its attributes; you'll need to rework your current file filter a bit to accommodate this.
boolean test(Path path, BasicFileAttributes attrs) {
...
}
Working example: http://screencast.com/t/buiyV9UiEa
You can try something like this:
//add this imports
import java.io.File;
import java.io.FilenameFilter;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
public static File[] getFiles(String path) {
File file = new File(path);
// Get the subdirectories.
String[] directories = file.list(new FilenameFilter() {
#Override
public boolean accept(File current, String name) {
return new File(current, name).isDirectory();
}
});
//Use a list to save the files returned from the recursive call
List<File> filesList = new ArrayList<File>();
if( directories != null){
for (String dir : directories) {
// Doing recursion
filesList.addAll( Arrays.asList(getFiles(path + File.separator + dir)) );
}
}
// Get the files inside the directory.
FileFilter fileFilter = new FileFilter();
File[] files = file.listFiles(fileFilter);
//Merge the rest of the files with the files
//in the current dir
if( files != null)
filesList.addAll( Arrays.asList(files) );
return filesList.toArray(new File[filesList.size()]);
}
Code tested and working. Hope this helps.
import java.util.Arrays;
import java.util.ArrayList;
Put a fail-safe right after you initialize file (in case of a bad path on the first call).
if (!file.isDirectory()) return new File[0];
And change the last part of your code to:
FileFilter fileFilter = new FileFilter();
ArrayList<File> files = new ArrayList(Arrays.asList(file.listFiles(fileFilter)));
for (String dir : directories) {
files.addAll(Arrays.asList(getFiles(dir)));
}
return files.toArray(new File[0]);
(the toArray method expands the array that you pass to it if it's too small) Ref
You should do something like this:
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
public static File[] getFiles(String path) {
File file = new File(path);
String[] directories = file.list(new FilenameFilter() {
#Override
public boolean accept(File current, String name) {
return new File(current, name).isDirectory();
}
});
ArrayList<File> files = Arrays.asList(file.listFiles(new FileFilter()));
for (String dir : directories) {
files.addAll(getFiles(dir));
}
return files.toArray(new File[list.size()]);
}
The new File[list.size()] is required because otherwise file.toArray() would return Object[].
Also, you should use a lambda expression instead of FilenameFilter, like so:
String[] directories = file.list((File current, String name) -> {
return new File(current, name).isDirectory();
});

From File[] files to directory

I have a problem with that code:
public class Files {
public static void main(String[] args) throws IOException {
// filter files AAA.txt and BBB.txt from another's
File f = new File("d:\\dir"); // current directory
File f1 = new File("d:\\dir1\\");
FilenameFilter textFilter = new FilenameFilter() {
public boolean accept(File dir, String name) {
if (name.startsWith("A") && name.endsWith(".TXT")) {
//System.out.println(name);
return true;
}
else if (name.startsWith("B") && name.endsWith(".TXT")) {
//System.out.println(name);
return true;
}
else {
//System.out.println(name);
return false;
}
}
};
File[] files = f.listFiles(textFilter);
for (File file : files) {
if (file.getName().startsWith("A") ) {
//here save file to d:\\folder1\\
}
}
}
}
How can I save files with specific name in example AAA.txt to folder1 and BBB.txt to folder 2. Thanks for any examples
From Files class from Java 7:
Use move(Path source, Path target, CopyOption... options)
import static java.nio.file.StandardCopyOption.*;
import java.nio.file.FileSystem;
import java.nio.file.Path;
import java.nio.file.Files;
...
for (File file : files) {
if (file.getName().startsWith("A") ) {
//here save file to d:\\folder1\\
// convert file to Path object use toPath() method.
Path targetFilePath = FileSystems.getDefault().getPath("d:\\folder1\\").resolve(file.getFileName())
Files.move(file.toPath(), targetFilePath , REPLACE_EXISTING);
}
}

Recursively file search not working

What i wanna do is to recursively search for some files on the external sd-card. The problem is that the code is looking ok, but (assuming .txt files) it only shows me 7 files out of 100+ that are being spread throughout folders.
The code is this:
file = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
void makelist(File file){
if(file.isFile()){
if(SimpleAdapter.getFileType(file)==null)
mis.add(file);
else if(SimpleAdapter.getFileType(file).equalsIgnoreCase("text"))
doc.add(file);
}else if(file.isDirectory()){
for(File f:file.listFiles())
makelist(f);
}
}
Any idea how could i make it run correctly?
Assuming you are building two lists (misc files and doc files), try with below code which all all files other than text files to misc and text files to doc.
if(SimpleAdapter.getFileType(file) == null || !SimpleAdapter.getFileType(file).equalsIgnoreCase("text"))
mis.add(file);
else
doc.add(file);
Not sure why it is not working for you. Tried a test program and it worked perfectly...
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class FileChecker
{
/**
* #param args
*/
public static void main(String[] args) {
SimpleAdapterTest adapter = new SimpleAdapterTest();
adapter.makelist(new File("C:\\MYFolder"));
adapter.showList();
}
}
class SimpleAdapterTest
{
List<File> mis = new ArrayList<File>();
List<File> doc = new ArrayList<File>();
public static String getFileType(File f)
{
String Name = f.getName();
if (f.getName().endsWith(".txt") || Name.endsWith(".TXT")
|| Name.endsWith(".inf") || Name.endsWith(".INF"))
return "text";
return null;
}
public void makelist(File file){
if(file.isFile()){
if(SimpleAdapterTest.getFileType(file)==null)
mis.add(file);
else if(SimpleAdapterTest.getFileType(file).equalsIgnoreCase("text"))
doc.add(file);
}else if(file.isDirectory()){
for(File f:file.listFiles())
makelist(f);
}
}
public void showList()
{
for(File miscFile : mis)
{
System.out.println("Misc files = " + miscFile.getName());
}
for(File docfile : doc)
{
System.out.println("Doc files = " + docfile.getName());
}
}
}

Categories