Java, searching through folders to match a name
I am using Java to search for a file or folder that matches a specific case. For instance I want to search through all the files and folders and iterate through them as many times as necessary until I find a result.
The catch
I am searching for files and folders through a binary image of a file system. This means I doubt there are any preexisting classes such java.file.*
to do it for me. If it helps, I can tell you that I can tell the difference between files and folders easily enough. (a folder is flagged as 0x20)
The only way I can think of is to do a standard loop and iterate several times, but this limits开发者_运维技巧 me if a file or folder is several folders deep.
All input greatly welcome
Edit
Just to clarify, I'm using a binary image and searching though it for directories.
I think the term "directory" could be misleading. Given an initial vaule of 0 I want to examine a series of bytes. If in the correct place I encounter a 0x20 (directory marker), I need to jump to a new location in the binary image and start searching again. If I encounter 0x20 again, I need to jump and start again; when finished I return to the point I was and continue to search for another 0x20. I need to do this until I have no more 0x20's in specific spots.
I can do this using n loops but that will only take me n directorys deep. I am wondering if anyone has any ideas on how to do this until there are no more directory markers.
Not really sure if this clarifies things but I hope it does.
EDIT This is code that I'm using and im getting a stack overflow error. any ideas on how i can improve it?
public boolean isDirectory(int dirAttr)
{
if (dirAttr == dir.ATTR_DIRECTORY)
return true;
else return false;
}
public void searchDirectory(int clusterNum, String name)
{
for (int i = 0; i<32;i++)
{
if(dir.DIR_NameS(clusterNum, i).contains(name))
{
System.out.println("Found a Match");
System.out.println("File name = " + dir.DIR_NameS(clusterNum, i));
System.out.println("File size in bytes = "+dir.DIR_FileSize(clusterNum, i));
System.out.println("File starting cluster = "+dir.DIR_FstClusLO(clusterNum, i));
System.out.println();
}
if(this.isDirectory(dir.DIR_Attr(clusterNum, i)))
{
searchDirectory(dir.DIR_FstClusLO(clusterNum, i), name);
}
}
}
How you interface with this image? It's just a plain array of bytes?
In this case you can't do it in Java without implementing something that is able to parse the FAT16 structure (or finding an api to interface with file systems saved as files), so you should go here and learn the structure of the file allocation table..
I can do this using n loops but that will only take me n directorys deep. I am wondering if anyone has any ideas on how to do this until there are no more directory markers.
This kind of thing is done by using recursion, or a stack (at a deeper level, these are equivalent).
For the recursive solution, you'll have a method that looks through a folder and calls itself whenever it spots a subfolder. The list could be a parameter passed to the method, to which results are appended.
For the stack-based solution, you create a stack (or list) of directories that need to be searched. It starts with the root directory as its only content. Then while the stack is non-empty, you remove one directory from it, search through that directory and add all subdirectories to the stack and all matching files to the list of results. Repeat until the stack is empty.
The only way I can think of is to do a standard loop and iterate several times, but this limits me if a file or folder is several folders deep [...] I can do this using n loops but that will only take me n directorys deep. I am wondering if anyone has any ideas on how to do this until there are no more directory markers.
It sounds to me that you're having trouble with the recursive part rather than the IO part. Here's an outline of the algorithm for you:
public class RecurseDirectories {
static String image =
";@root=<f1,f2,@d1,@d2,@foo>;@d1=<x,@d1d1>;@d2=<y>;@d1d1=<a,b>;@bar=<>;";
String getContent(String dir, String image) {
return image.replaceAll(
"^.*;dir=<(.*?)>.*$|.*".replace("dir", dir),
"$1"
);
}
String[] iterable(String content) {
return content.split(",");
}
boolean isDirectory(String file) {
return file.startsWith("@");
}
void recurse(String image, String path, String dir) {
String dirContent = getContent(dir, image);
System.out.format("%s%s=<%s>%n", path, dir, dirContent);
for (String file : iterable(dirContent)) {
if (isDirectory(file)) {
recurse(image, path + dir, file);
}
// do any checking of file here
}
}
public static void main(String[] args) {
new RecurseDirectories().recurse(image, "", "@root");
}
}
This prints out:
@root=<f1,f2,@d1,@d2,@foo>
@root@d1=<x,@d1d1>
@root@d1@d1d1=<a,b>
@root@d2=<y>
@root@foo=<>
getContent
, isDirectory
, and the format of the image string is specific to this example, but recurse
is basically what you want to study. It is a form of depth-first search.
Make sure that there is no self-containment in the directory tree structure (possible due to symlinks etc), because that would cause an infinite recursion (until it causes a StackOverflowError
).
Also, if you want to avoid going through the image several times throughout the search, you can go through it once to build a tree, and then recurse
through that tree (i.e. basically getContent
is what you want to optimize).
FileUtils.listFiles(rootDir, null, true)
(from commons-io) will give you all files from a given root directory.
Then you can iterate the returned collection to see if a File
in it matches your criteria.
Notes: This is meant to be platform-independent. The true
argument means that all files are fetched recursively.
精彩评论