Reputation: 55
static boolean fileFound;
static String fileName = "tumblr.txt";
public static void searchFile(File f) //File f is "C:\\"
{
try
{
if(f.isDirectory())
{
File [] fi = f.listFiles();
for(int i=0;i<fi.length;i++)
{
if(fileFound==true)
{
break;
}
System.out.println(fi[i].getName());
searchFile(fi[i]);
}
}
else
{
if(f.getName().equalsIgnoreCase(fileName) || f.getName().toLowerCase().startsWith(fileName.toLowerCase()))||(f.getName().toLowerCase().endsWith(fileName.toLowerCase())))
{
System.out.print("file found " + f.getAbsolutePath());
fileFound=true;
}
}
}
catch(Exception e)
{
}
}
This is my code for searching a text file called tumblr.txt
or it can be any file type on my computer. The above code works, but it's really slow. It took like 2 minutes to find that file located on my desktop. Is there a way to do it this with a faster search speed? Just like the Start menu's "search programs and files" feature. You can provide me with links if you want.
Upvotes: 1
Views: 4839
Reputation: 2076
If you use several threads you can perform the search faster.
I post this class an example, it uses a pool of threads to scan directories and another thread to check the matching of the name against the files contained in those directories. The two classes of threads are connected with two blocking queues, one for the directories to search, and another for the files to match. When the file is found, the threads that scan dirs are signalled to end with a poison pill. There is an AtomicLong variable to track the directory count in progress.
In my laptop it scans the whole hd in 120 seconds more or less. I hope this will help.
import java.io.File;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicLong;
public class FindFile {
private static final File POISONPILL = new File("");
private static class RunnableDirSearch implements Runnable {
private final BlockingQueue<File> dirQueue;
private final BlockingQueue<File> fileQueue;
private final AtomicLong count;
private final int num;
public RunnableDirSearch(final BlockingQueue<File> dirQueue, final BlockingQueue<File> fileQueue, final AtomicLong count, final int num) {
this.dirQueue = dirQueue;
this.fileQueue = fileQueue;
this.count = count;
this.num = num;
}
@Override
public void run() {
try {
File dir = dirQueue.take();
while (dir != POISONPILL) {
final File[] fi = dir.listFiles();
if (fi != null) {
for (final File element : fi) {
if (element.isDirectory()) {
count.incrementAndGet();
dirQueue.put(element);
} else {
fileQueue.put(element);
}
}
}
final long c = count.decrementAndGet();
if (c == 0) {
end();
}
dir = dirQueue.take();
}
} catch (final InterruptedException ie) {
// file found or error
}
}
private final void end() {
try {
fileQueue.put(POISONPILL);
} catch (final InterruptedException e) {
// empty
}
for (int i = 0; i < num; i++) {
try {
dirQueue.put(POISONPILL);
} catch (final InterruptedException e) {
// empty
}
}
}
}
private static class CallableFileSearch implements Callable<File> {
private final BlockingQueue<File> dirQueue;
private final BlockingQueue<File> fileQueue;
private final String name;
private final int num;
public CallableFileSearch(final BlockingQueue<File> dirQueue, final BlockingQueue<File> fileQueue, final String name, final int num) {
this.dirQueue = dirQueue;
this.fileQueue = fileQueue;
this.name = name;
this.num = num;
}
@Override
public File call() throws Exception {
File file = fileQueue.take();
while (file != POISONPILL) {
final String filename = file.getName().toLowerCase();
final String lf = name.toLowerCase();
if (filename.equalsIgnoreCase(name) || filename.startsWith(lf) || filename.endsWith(lf)) {
end();
return file;
}
file = fileQueue.take();
}
return null;
}
private final void end() {
for (int i = 0; i < num; i++) {
try {
dirQueue.put(POISONPILL);
} catch (final InterruptedException e) {
// empty
}
}
}
}
private final String filename;
private final File baseDir;
private final int concurrency;
private final AtomicLong count;
public FindFile(final String filename, final File baseDir, final int concurrency) {
this.filename = filename;
this.baseDir = baseDir;
this.concurrency = concurrency;
count = new AtomicLong(0);
}
public File find() {
final ExecutorService ex = Executors.newFixedThreadPool(concurrency + 1);
final BlockingQueue<File> dirQueue = new LinkedBlockingQueue<File>();
final BlockingQueue<File> fileQueue = new LinkedBlockingQueue<File>(10000);
for (int i = 0; i < concurrency; i++) {
ex.submit(new RunnableDirSearch(dirQueue, fileQueue, count, concurrency));
}
count.incrementAndGet();
dirQueue.add(baseDir);
final Future<File> c = ex.submit(new CallableFileSearch(dirQueue, fileQueue, filename, concurrency));
try {
final File f = c.get();
return f;
} catch (final Exception e) {
return null;
} finally {
ex.shutdownNow();
}
}
public static void main(final String[] args) {
final String filename = "test.h2.db23";
final File baseDir = new File("C:/");
final FindFile ff = new FindFile(filename, baseDir, 6);
final long ini = System.currentTimeMillis();
final File f = ff.find();
final long end = System.currentTimeMillis();
System.out.println(f + " " + (end - ini) + " ms");
}
}
Upvotes: 2