Return files values of recursive method - java

I would like to return values of a recursive method which list all files in directory and subdirectories. The goal is to create a HashSet of md5 file values.
For the moment the code works fine but just in root dir, not in recursive.
static Set<String> localMd5Listing() throws Exception {
List<String> localMd5List = new ArrayList<String>();
if(!baseModDirectoryFile.exists()){
System.out.println("baseModDirectory doesn't exist, check your baseModDirectory variable.");
}
else{
if(baseModDirectoryFile.isDirectory()){
File[] paths = baseModDirectoryFile.listFiles();
if(paths != null){
for(File path:paths){
if(path.isFile()){
FileInputStream fis = new FileInputStream(path);
String md5 = org.apache.commons.codec.digest.DigestUtils.md5Hex(fis);
fis.close();
localMd5List.add(md5);
}
else if(path.isDirectory()){
listChildren(path);
//Check md5 for children files as path.isFile condition
}
}
}
}
}
Set<String> localSet = new HashSet<String>();
localSet.addAll(localMd5List);
localMd5List.clear();
localMd5List.addAll(localSet);
return localSet;
}
listChildren method for recursive result :
public static void listChildren(File dir) throws IOException{
File[] files = dir.listFiles();
for(File file:files){
if(file.isDirectory()){
listChildren(file);
}
else{
//Return file variable to use them in localMd5Listing()
}
}
}
Unfortuntely I didn't know how to link the 2 methods to return values of listChildren() in localMd5Listing(). I think it's not the good way to have a listFile() in the first method too.
Thank you !

Extract the if statement in localMD5listing into a method recurseMD5 that takes a File argument and the list of hashes for update. Then start off the process by calling
recurseMD5(baseModDirectoryFile, localmd5List);
and in recurseMD5 you just recurse on all listFiles() when the parameter is a directory. If, OTOH, it is a regular file, you add the md5.
void recurseMD5(File it, List<String> hashes) {
if (it.isDirectory) {
for (File f : it.listFiles()) recurseMD5(f, hahses);
}
else {
// process MD5 hash of file
}
}

the basic setup you want is something like the following pseudocode
public List<string> getAllHashes() {
List<String> hashes = new List<String>();
//calculate all the hashes
foreach(directory d in directories) {
hashes.add(directory.getAllHashes());
}
return hashes;
}
I know that this is no full code whatsoever, but with this you should be able to make the recursive loop. Don't forget to check if there actually ARE directories in there, or you might get a nullpointer!

Related

How to get oldest file in a directory using Java

Are there any methods for obtaining the oldest file in a directory using java?
I have a directory i write log files to and would like to delete log files after ive recorded over 500 log files (but only want to delete the oldest ones).
The only way i could conceive myself is:
Get the list of files using the File.listFiles() method
Loop through each File
Store the last modified date using File.lastModified() and compare with File from loop iteration, keep the oldest lastModified()
The inconvenient aspect of this logic is that i would have to loop the log directory every time i want to get the oldest files and that does not seem the most efficient.
i expected the java.io.File library would have a method to get the oldest file in a directory but it doesnt seem to exist, or i havent found it. If there is a method for obtaining the oldest file in a directory or a more convenient approach in programming the solution, i would love to know.
Thanks
Based off of #Yoda comment, i figured i would answer my own question.
public static void main(String[] args) throws IOException {
File directory = new File("/logFiles");
purgeLogFiles(directory);
}
public void purgeLogFiles(File logDir){
File[] logFiles = logDir.listFiles();
long oldestDate = Long.MAX_VALUE;
File oldestFile = null;
if( logFiles != null && logFiles.length >499){
//delete oldest files after theres more than 500 log files
for(File f: logFiles){
if(f.lastModified() < oldestDate){
oldestDate = f.lastModified();
oldestFile = f;
}
}
if(oldestFile != null){
oldestFile.delete();
}
}
}
Unfortunately, you're gonna have to just walk the filesystem. Something like:
public static void main(String[] args) throws IOException {
String parentFolder = "/var/log";
int numberOfOldestFilesToFind = 5;
List<Path> oldestFiles = findOldestFiles(parentFolder, numberOfOldestFilesToFind);
System.out.println(oldestFiles);
}
private static List<Path> findOldestFiles(String parentFolder, int numberOfOldestFilesToFind) throws IOException {
Comparator<? super Path> lastModifiedComparator =
(p1, p2) -> Long.compare(p1.toFile().lastModified(),
p2.toFile().lastModified());
List<Path> oldestFiles = Collections.emptyList();
try (Stream<Path> paths = Files.walk(Paths.get(parentFolder))) {
oldestFiles = paths.filter(Files::isRegularFile)
.sorted(lastModifiedComparator)
.limit(numberOfOldestFilesToFind)
.collect(Collectors.toList());
}
return oldestFiles;
}

Matching a String with a File Name

I'm writing a program that does various data analysis functions for use with Excel.
I need a way of returning file names of documents so I can search through them and find the ones I want.
I need to be able to take a string, saved as a variable, and use it to return the name of every document in a folder whose file name contains that string.
This will be used to sift through pre-categorized sections of data. Ideally I would save those documents' file names in a string array for later use within other functions.
private List<String> searchForFileNameContainingSubstring( String substring )
{
//This is assuming you pass in the substring from input.
File file = new File("C:/Users/example/Desktop"); //Change this to the directory you want to search in.
List<String> filesContainingSubstring = new ArrayList<String>();
if( file.exists() && file.isDirectory() )
{
String[] files = file.list(); //get the files in String format.
for( String fileName : files )
{
if( fileName.contains( substring ) )
filesContainingSubstring.add( fileName );
}
}
for( String fileName : filesContainingSubstring )
{
System.out.println( fileName ); //or do other operation
}
return filesContainingSubstring; //return the list of filenames containing substring.
}
Using this method, you could pass in the input from the user as the string you want the filename to contain. The only other thing you need to change is where you want in your directory to start searching for files, and this program only looks in that directory.
You could further look recursively within other directories from the starting point, but I won't add that functionality here. You should definitely look into it though.
This also assumes that you are looking for everything within the directory, including other folders and not just files.
You can get the list of all the files in a directory and then store them in an array. Next, using the java.io.File.getName() method, you can get the names of the files. Now you can simply use the .indexOf() method to check whether the string is a substring of the file name. I assume that all the items in the directory of concern are files and not sub directories.
public static void main(String[] args) throws IOException {
File[] files = new File("X:/").listFiles(); //X is the directory
String s <--- the string you want to check filenames with
for(File f : files){
if(f.getName().toLowerCase().indexOf(s.toLowerCase()) != -1)
System.out.println(f.getName());
}
}
This should display the names of all those files in the directory X:\ whose names include the String s.
References
This question: How do I iterate through the files in a directory in Java?
The java.io.File.getName() method
Statutory edit info
I have edited this answer simply to replace the previous algorithm, for checking the existence of a substring in a string, with the one that is currently used in the code above.
Here is an answer to search the file recursively??
String name; //to hold the search file name
public String listFolder(File dir) {
int flag;
File[] subDirs = dir.listFiles(new FileFilter() {
#Override
public boolean accept(File pathname) {
return pathname.isDirectory();
}
});
System.out.println("File of Directory: " + dir.getAbsolutePath());
flag = Listfile(dir);
if (flag == 0) {
System.out.println("File Found in THe Directory: " + dir.getAbsolutePath());
Speak("File Found in THe Directory: !!" + dir.getAbsolutePath());
return dir.getAbsolutePath();
}
for (File folder : subDirs) {
listFolder(folder);
}
return null;
}
private int Listfile(File dir) {
boolean ch = false;
File[] files = dir.listFiles();
for (File file : files) {
Listfile(file);
if (file.getName().indexOf(name.toLowerCase()) != -1) {//check all in lower case
System.out.println(name + "Found Sucessfully!!");
ch = true;
}
}
if (ch) {
return 1;
} else {
return 0;
}
}

Java nio, get all subfolders of some folder

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);
}
}

How can move file from one directory to another

I am sorry,I modified my entire question.
I want to move some specific files(based on fileExtension) from one directory to another.
For this, I plan to write 2 functions names are ListOfFileNames and MovingFiles.
If you pass directorypath and filetype as a arguments toListOfFileNames(),it returns List<File>data.this list have entire file path.
MovingFiles() move files from source Directory to destination.
I tried MovingFiles function, in the following way.It's not working.
public void MovingFiles(String SourcePath,String directoryPath,String fileType) throws IOException
{
ExternalFileExecutions ExternalFileExecutionsObject=new ExternalFileExecutions();
List<File> fileNames=ExternalFileExecutionsObject.ListOfFileNames(SourcePath, fileType);
for (int fileIndex = 0; fileIndex < fileNames.size(); fileIndex++)
{
fileNames[fileIndex].renameTo(new File(directoryPath+"/" + fileNames[fileIndex].getName()))
}
}
I think, I need to convert List<File> to List<String>.that's why Previously I asked like that.
#tbodt replyed for my question.I failed to integrate his answer in my function.so I modified my question.
Again sorry, for modifying my entire question.
Thanks.
If you want to get a List<String> with each element the canonical path of the corresponding file, this is how:
List<String> list = new ArrayList<String>();
for (File file : finalListNames)
list.add(file.getCanonicalPath());
If that's not what you want, please clarify.
If understand you, using guava, I would write it in this way:
public static List<File> listOfFiles(){
return Lists.newArrayList(new File("source.txt"), new File("test.txt"));
}
public static List<String> listOfFileNames(){
return Lists.transform(listOfFiles(), new Function<File, String>() {
public String apply(File input) {
return input.getAbsolutePath();
}
});
}
You cant convert it. But what you can is that you can retrieve the name (what ever it is) while iterating through File list. A very handy solution would be LINQ, and select
This my answer. I used #tbodt code in my code.
public void MovingFiles(String SourcePath,String directoryPath,String fileType) throws IOException
{
ExternalFileExecutions ExternalFileExecutionsObject=new ExternalFileExecutions();
List<File> fileNames=ExternalFileExecutionsObject.ListOfFileNames(SourcePath, fileType);
List<String> list = new ArrayList<String>();
for (File file : fileNames)
list.add(file.getCanonicalPath());
for (int fileIndex = 0; fileIndex < list.size(); fileIndex++)
{
File file=new File(list.get(fileIndex));
file.renameTo(new File(directoryPath+"/",file.getName()));
}
}
you move a file from one directory to another directory with the same file name
try{
File afile =new File("C:\\folder1\\file1.txt");
if(afile.renameTo(new File("C:\\folder2\\" + afile.getName()))){
System.out.println("File is moved successful!");
}else{
System.out.println("File is failed to move!");
}
}catch(Exception e){
e.printStackTrace();
}

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;
}

Categories

Resources