java - search hardisk for a type of file

dropadrop

Gawd
Joined
Feb 28, 2001
Messages
569
Are there any ready tools for this? I'm making a program that should search the hardisk for all files with a certain extension (fonts), and save a list of them for further use. Anyone know what the easiest way to get started would be?
 
I don't think there's a already built in tool to do it. Fortuneatly it's rather easy to do. All that is needed resides in the "java.io.File" Class.

Get all of the drives of the system by using "java.io.File.listRoots()"

Then from that you call "java.io.File.listFiles" to get all the files and directories of that root folder.

With this you should easily be able to go everywhere on the computer.

Cheers!
 
Thanks for the help. I managed to find a few examples of how to use listFiles, and got it to work in a way that it lists everything in folders and subfolders. I'm now trying to get it to filter out so it only shows files with a certain extension and it's not working. The following is combined from some of the examples I found:

Code:
import java.util.*;
import java.io.*;


/**
* @author javapractices.com
* @author Alex Wong
*/
public final class FileListing {

  /**
  * Demonstrate use.
  */
  public static void main(String[] aArguments) throws FileNotFoundException {
  	
  	// Syötteenä tuleva kansio josta halutaan etsiä (ja syvempää)
    File tempDir = new File(aArguments[0]);
    
    // Kutsuu metodia getFileListing joka palauttaa listauksen
    List files = FileListing.getFileListing( tempDir );

    //print out all file names, and display the order of File.compareTo
    Iterator filesIter = files.iterator();
    while( filesIter.hasNext() ){
      System.out.println( filesIter.next() );
    }
  }

  /**
  * Recursively walk a directory tree and return a List of all
  * Files found; the List is sorted using File.compareTo.
  *
  * @param aStartingDir is a valid directory, which can be read.
  *
  * Otherwise ok, but needs a filter to leave only the fonts
  */
  static public List getFileListing( File aStartingDir ) throws FileNotFoundException{
    validateDirectory(aStartingDir);
    List result = new ArrayList();
    	
	
    File[] filesAndDirs = aStartingDir.listFiles(new PhilePhilter());
    List filesDirs = Arrays.asList(filesAndDirs);
    Iterator filesIter = filesDirs.iterator();
    File file = null;
    while ( filesIter.hasNext() && ) {
      file = (File)filesIter.next();
      result.add(file); //always add, even if directory
      if (!file.isFile()) {
        //must be a directory
        //recursive call!
        List deeperList = getFileListing(file);
        result.addAll(deeperList);
      }

    }
    Collections.sort(result);
    return result;
  }
  
  
  /*
   * Class to filter out files that don't have
   * the correct extension.
   */
   
  static class PhilePhilter implements FilenameFilter 
  {
  	public boolean accept(File dir, String file) 
  	{
  		return (file.toUpperCase().indexOf(".GIF") != -1);
  	}
  	
  }

  /**
  * Directory is valid if it exists, does not represent a file, and can be read.
  */
  static private void validateDirectory (File aDirectory) throws FileNotFoundException {
    if (aDirectory == null) {
      throw new IllegalArgumentException("Directory should not be null.");
    }
    if (!aDirectory.exists()) {
      throw new FileNotFoundException("Directory does not exist: " + aDirectory);
    }
    if (!aDirectory.isDirectory()) {
      throw new IllegalArgumentException("Is not a directory: " + aDirectory);
    }
    if (!aDirectory.canRead()) {
      throw new IllegalArgumentException("Directory cannot be read: " + aDirectory);
    }
  }
}

I believe the PhilePhilter should work as it's almost a direct rip from the original example. The problem is probably with the way it's implemented... Is it returning a value that I should allwasy check somewhere?
 
dropadrop said:
Thanks for the help. I managed to find a few examples of how to use listFiles, and got it to work in a way that it lists everything in folders and subfolders. I'm now trying to get it to filter out so it only shows files with a certain extension and it's not working. The following is combined from some of the examples I found:
Indeed, I did notice your code is made out of many diferent sources all mixed into one. That is cannibalism worthy of the greatest programmer :D
dropadrop said:
I believe the PhilePhilter should work as it's almost a direct rip from the original example. The problem is probably with the way it's implemented... Is it returning a value that I should allwasy check somewhere?
Well, i got good news and bad news. The good news is that yes, the PhilePhilter works great. The bad news is that the rest doesn't :eek:

Here is the best advice I can give you. Remake the "getFileListingFile aStartingDir)" method like this.

At the start of the method put the recursive code. Meaning that you take all of the directories of the variable "aStartingDir". That will require yet another FileFilter. Once you have all of the directories, reinvoke your method with them as the argument, collecting all of their results into a massive List.

And the second part. just take "aStartingDir" and list all of his files you want using your already made PhilePhilter class. You add that result to the big List and you return it. All in all that's what I would do, in fact it's what I did.

Hope it helped.
 
Took a moment, but I understand what the problem is. It's filtering out all the folders so it never gets deep enough to find the files it's looking for... I tested giving a folder that contains gif files (as opposed to a folder a bit higher in the hierarchy) and it listed them just fine...

So basicly you are saying I should let it create a list with all the files and folders, and then I should filter down that list to find the ones I need?
 
dropadrop said:
So basicly you are saying I should let it create a list with all the files and folders, and then I should filter down that list to find the ones I need?
Sure, that works well to. I't not how I would design it, but I just tested it and it works fine. In order for it to work just remake your PhilePhilter to return true either if your file is a directory, or if the file is a .gif file.

And once that is done you will have a List of all the directories and all the .gif files on the computer. So just create a loop that will filter out all the directories out of the List.

Courage, you're almost there!
 
I think narrowing down a full list will be the way it should be done, as finally the program will be searching for a multitude of differant file-extensions, and processing them in differant ways. I tried to create a method (getGifListing) that would narrow down the created list, but it does'nt seem to narrow down anything...

Any idea what I'm doing wrong?

Code:
import java.util.*;
import java.io.*;


/**
* @author javapractices.com
* @author Alex Wong
*/
public final class FileListing {

  /**
  * Demonstrate use.
  */
  public static void main(String[] aArguments) throws FileNotFoundException {
  	
  	// Receives the root folder where the search is started from
    File tempDir = new File(aArguments[0]);
    
    // get a fileListing from local disk
    List files = FileListing.getFileListing( tempDir );
    
    // narrows down the previous list to only include files with .GIF extensions
    List sortedFiles = FileListing.getGifListing( files, ".GIF" );

    //print out all file names, and display the order of File.compareTo
    Iterator filesIter = sortedFiles.iterator();
    while( filesIter.hasNext() ){
      System.out.println( filesIter.next() );
    }
  }

  /**
  * Recursively walk a directory tree and return a List of all
  * Files found; the List is sorted using File.compareTo.
  *
  * @param aStartingDir is a valid directory, which can be read.
  *
  * Otherwise ok, but needs a filter to leave only the fonts
  */
  static public List getFileListing( File aStartingDir ) throws FileNotFoundException{
    validateDirectory(aStartingDir);
    List result = new ArrayList();
	
    File[] filesAndDirs = aStartingDir.listFiles();
    List filesDirs = Arrays.asList(filesAndDirs);
    Iterator filesIter = filesDirs.iterator();
    File file = null;
    
    while ( filesIter.hasNext() ) {
      file = (File)filesIter.next();
      result.add(file); //always add, even if directory
      if (!file.isFile()) {
        //must be a directory
        //recursive call!
        List deeperList = getFileListing(file);
        result.addAll(deeperList);
      }

    }
    Collections.sort(result);
    return result;
  }
  
  // Search a list for specified files and return a new list only including them.
  
  static public List getGifListing( List aStartingPoint, String name ) {
  	
  	List allFiles = aStartingPoint;
  	List sortedFiles = new ArrayList();
  	
  	Iterator filesIter = allFiles.iterator();
  	File file = null;
  	
    while( filesIter.hasNext()) {
    	file = (File)filesIter.next();
    	if (file.getName().toUpperCase().indexOf(name) != -1);
    	sortedFiles.add(file);
    }
  	
  	return sortedFiles;
  	
  }
  
  
  /*
   * Class to filter out files that don't have
   * the correct extension.
   *
   * Thanks go to Google and Marco
   */
   
  static class PhilePhilter implements FilenameFilter 
  {
  	public boolean accept(File dir, String file) 
  	{
  		return (file.toUpperCase().indexOf(".GIF") != -1);
  	}
  	
  }

  /**
  * Directory is valid if it exists, does not represent a file, and can be read.
  */
  static private void validateDirectory (File aDirectory) throws FileNotFoundException {
    if (aDirectory == null) {
      throw new IllegalArgumentException("Directory should not be null.");
    }
    if (!aDirectory.exists()) {
      throw new FileNotFoundException("Directory does not exist: " + aDirectory);
    }
    if (!aDirectory.isDirectory()) {
      throw new IllegalArgumentException("Is not a directory: " + aDirectory);
    }
    if (!aDirectory.canRead()) {
      throw new IllegalArgumentException("Directory cannot be read: " + aDirectory);
    }
  }
}
 
I'm afraid that I must hand you a baseball bat so that you may hit yourself on the head with it. :eek:

No no, it's not a threat or anything like that, it's just that, well here, I'll show you the couple of lines with the mistake and try not to beat yourself to much about it. It's a common mistake, happened to everyone of us.

Code:
if (file.getName().toUpperCase().indexOf(name) != -1);
sortedFiles.add(file);

Once you get this fix, everything will be fine.

See ya!
 
It works fine now when I start it with c:\SomeFolder, but when I try to scan the whole harddisk with c:\ it crashes after a while. This is the error that comes from it:

C:\Documents and Settings\Mika\Omat tiedostot\my_java\fonts\Fonts\classes>java F
ileListing c:\
Exception in thread "main" java.lang.NullPointerException
at java.util.Arrays$ArrayList.<init>(Unknown Source)
at java.util.Arrays.asList(Unknown Source)
at FileListing.getFileListing(FileListing.java:45)
at FileListing.getFileListing(FileListing.java:55)
at FileListing.main(FileListing.java:20)

I guess this would mean that it has problems scanning some of the folders on my computer. As a wild guess it could be the folders who's names have a space in them?

edit: I tried adding a folder with a name that contained a space under c:/someFolder and it still worked...

edit2:

It gets weirder. I modified the code to see how far it's getting before crashing, and added one (system.out.println(..) line to it:
Code:
  static public List getFileListing( File aStartingDir ) throws FileNotFoundException{
    validateDirectory(aStartingDir);
    List result = new ArrayList();
	
    File[] filesAndDirs = aStartingDir.listFiles();

    // Test if it gets this far
    System.out.println("success 1");
    List filesDirs = Arrays.asList(filesAndDirs);
    Iterator filesIter = filesDirs.iterator();
    File file = null;
    
    while ( filesIter.hasNext() ) {
      file = (File)filesIter.next();
      result.add(file); //always add, even if directory
      if (!file.isFile()) {
        //must be a directory
        //recursive call!
        List deeperList = getFileListing(file);
        result.addAll(deeperList);
      }

    }
    Collections.sort(result);
    return result;
  }

For some reason it prints that out alot of times... If I test the program with the subfolder that still works it prints out success1 11 times. If I try it with the whole C drive it prints it out too many times to fit in the promt and then crashes.

I can't see how it's running through that point so many times? As far as I understand the recurssive part comes later, and that part should only be passed once?
 
Without going to deep into this problem it seems that the Windows platform has some special features that is problamatic for the JVM. To not go into details I suggest that you simply modify this piece of code. It should work normaly afterwards.

Code:
File[] filesAndDirs = aStartingDir.listFiles();

// New code
if (filesAndDirs == null)
	return result;
// End new code

List filesDirs = Arrays.asList(filesAndDirs);
 
dropadrop said:
You are a lifesaviour!

If I ever come to the states I'll buy you a beer. :D
American beer :mad:

In anycase you'd have a hard time finding me in the states since I'm a Canadian. But if your offer also applies to the Canadian beer, count me in ;)

As always, spread some Java LOVE Power :eek:
 
Nemezer said:
American beer :mad:

In anycase you'd have a hard time finding me in the states since I'm a Canadian. But if your offer also applies to the Canadian beer, count me in ;)

As always, spread some Java LOVE Power :eek:

I'm more into european beer, but I'm ready to try canadian :D
 
Nemezer said:
Code:
if (file.getName().toUpperCase().indexOf(name) != -1);
sortedFiles.add(file);
Just thought I'd point out that Java does have a contains(String) method, which is much more succinct. Perhaps more relevantly, there is an endsWith(String) method that's probably even more useful (or accurate, at least) for the purposes of a filename extension filter.
 
Back
Top