Java - поиск файлов в каталоге

Это должно быть просто, но я не могу его получить - "Напишите программу, которая ищет конкретное имя файла в данном каталоге". Я нашел несколько примеров жесткого кодированного имени файла и каталога, но мне нужно, чтобы имя каталога и файла было введено пользователем.

public static void main(String[] args) {
    String fileName = args[0]; // For the filename declaration
    String directory;     
    boolean found;

    File dir = new File(directory);

    File[] matchingFiles = dir.listFiles(new FilenameFilter() {
        public boolean accept(File dir, String fileName) {
            return true;
        }
    });

}

Ответ 1

вы можете попробовать что-то вроде этого:

import java.io.*;
import java.util.*;
class FindFile 
{
    public void findFile(String name,File file)
    {
        File[] list = file.listFiles();
        if(list!=null)
        for (File fil : list)
        {
            if (fil.isDirectory())
            {
                findFile(name,fil);
            }
            else if (name.equalsIgnoreCase(fil.getName()))
            {
                System.out.println(fil.getParentFile());
            }
        }
    }
    public static void main(String[] args) 
    {
        FindFile ff = new FindFile();
        Scanner scan = new Scanner(System.in);
        System.out.println("Enter the file to be searched.. " );
        String name = scan.next();
        System.out.println("Enter the directory where to search ");
        String directory = scan.next();
        ff.findFile(name,new File(directory));
    }
}

Вот результат:

J:\Java\misc\load>java FindFile
Enter the file to be searched..
FindFile.java
Enter the directory where to search
j:\java\
FindFile.java Found in->j:\java\misc\load

Ответ 2

Это похоже на вопрос о домашнем задании, поэтому я просто дам вам несколько указателей:

Попробуйте дать хорошие отличительные имена переменных. Здесь вы сначала использовали "fileName" для каталога, а затем для файла. Это сбивает с толку и не поможет решить проблему. Используйте разные имена для разных вещей.

Вы не используете Scanner для чего-либо, и он здесь не нужен, избавиться от него.

Кроме того, метод accept должен возвращать логическое значение. Прямо сейчас вы пытаетесь вернуть строку. Boolean означает, что он должен либо возвращать true, либо false. Например, return a > 0; может возвращать true или false, в зависимости от значения a. Но return fileName; просто вернет значение fileName, которое является строкой.

Ответ 3

Если вы хотите использовать динамический фильтр имен файлов, вы можете реализовать FilenameFilter и передать в конструкторе динамическое имя.

Конечно, это подразумевает, что вы должны создавать экземпляр каждый раз в классе (накладные расходы), но он работает

Пример:

public class DynamicFileNameFilter implements FilenameFilter {

    private String comparingname;

    public DynamicFileNameFilter(String comparingName){
        this.comparingname = comparingName;
    }

    @Override
    public boolean accept(File dir, String name) {
        File file = new File(name);

        if (name.equals(comparingname) && !file.isDirectory())
            return false;

        else
            return true;
    }

}

то вы используете, где вам нужно:

FilenameFilter fileNameFilter = new DynamicFileNameFilter("thedynamicNameorpatternYouAreSearchinfor");
File[] matchingFiles = dir.listFiles(fileNameFilter);

Ответ 4

С ** Java 8 * существует альтернатива, которая использует потоки и lambdas:

public static void recursiveFind(Path path, Consumer<Path> c) {
  try (DirectoryStream<Path> newDirectoryStream = Files.newDirectoryStream(path)) {
    StreamSupport.stream(newDirectoryStream.spliterator(), false)
                 .peek(p -> {
                   c.accept(p);
                   if (p.toFile()
                        .isDirectory()) {
                     recursiveFind(p, c);
                   }
                 })
                 .collect(Collectors.toList());
  } catch (IOException e) {
    e.printStackTrace();
  }
}

Таким образом, это будет рекурсивно выводить все файлы:

recursiveFind(Paths.get("."), System.out::println);

И это будет поиск файла:

recursiveFind(Paths.get("."), p -> { 
  if (p.toFile().getName().toString().equals("src")) {
    System.out.println(p);
  }
});

Ответ 5

Я использовал другой подход для поиска файла с использованием стека. Помня, что в папке могут быть папки. Хотя это не быстрее, чем поиск в Windows (и я этого не ожидал), но он определенно дает правильный результат. Пожалуйста, измените код так, как хотите. Этот код изначально был создан для извлечения пути к файлу некоторого расширения файла:). Не стесняйтесь оптимизировать.

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Deepankar Sinha
 */
public class GetList {
    public List<String> stack;
    static List<String> lnkFile;
    static List<String> progName;

    int index=-1;
    public static void main(String args[]) throws IOException
    {

        //var-- progFile:Location of the file to be search. 
        String progFile="C:\\";
        GetList obj=new GetList();
        String temp=progFile;
        int i;
        while(!"&%@#".equals(temp))
        {
            File dir=new File(temp);
            String[] directory=dir.list();
            if(directory!=null){
            for(String name: directory)
            {
                if(new File(temp+name).isDirectory())
                    obj.push(temp+name+"\\");
                else
                    if(new File(temp+name).isFile())
                    {
                        try{
                            //".exe can be replaced with file name to be searched. Just exclude name.substring()... you know what to do.:)
                        if(".exe".equals(name.substring(name.lastIndexOf('.'), name.length())))
                        {
                            //obj.addFile(temp+name,name);
                            System.out.println(temp+name);
                        }
                        }catch(StringIndexOutOfBoundsException e)
                        {
                            //debug purpose
                            System.out.println("ERROR******"+temp+name);
                        }

                    }
            }}
            temp=obj.pop();
        }
        obj.display();

//        for(int i=0;i<directory.length;i++)
//        System.out.println(directory[i]);
    }

    public GetList() {
        this.stack = new ArrayList<>();
        this.lnkFile=new ArrayList<>();
        this.progName=new ArrayList<>();
    }
    public void push(String dir)
    {
        index++;
        //System.out.println("PUSH : "+dir+" "+index);
        this.stack.add(index,dir);

    }
    public String pop()
    {
        String dir="";
        if(index==-1)
            return "&%@#";
        else
        {
            dir=this.stack.get(index);
            //System.out.println("POP : "+dir+" "+index);
            index--;

        }
        return dir;
    }

    public void addFile(String name,String name2)
    {
        lnkFile.add(name);
        progName.add(name2);
    }

    public void display()
    {
        GetList.lnkFile.stream().forEach((lnkFile1) -> {
            System.out.println(lnkFile1);
        });
    }

}

Ответ 6

Следующий код помогает найти файл в каталоге и открыть его расположение

import java.io.*;
import java.util.*;
import java.awt.Desktop;
public class Filesearch2 {


    public static void main(String[] args)throws IOException {        
        Filesearch2 fs = new Filesearch2();
        Scanner scan = new Scanner(System.in);
        System.out.println("Enter the file to be searched.. " );
        String name = scan.next();
        System.out.println("Enter the directory where to search ");
        String directory = scan.next();
        fs.findFile(name,new File(directory));
    }
    public void findFile(String name,File file1)throws IOException
    {      
        File[] list = file1.listFiles();       
        if(list!=null)  
     {                          
        for(File file2 : list)
        {            
            if (file2.isDirectory())
            {
                findFile(name,file2);             
            }
            else if (name.equalsIgnoreCase(file2.getName()))
            {                                                              
                System.out.println("Found");                
                System.out.println("File found at : "+file2.getParentFile());
                System.out.println("Path diectory: "+file2.getAbsolutePath());
                String p1 = ""+file2.getParentFile();
                File f2 = new File(p1);
                Desktop.getDesktop().open(f2);                               
            }                      
        }        
      }
    }        
}

Ответ 7

Этот метод будет рекурсивно искать через каждый каталог, начиная с корня, до тех пор, пока не будет найдено имя файла, или все остальные результаты возвращаются в нуль.

public static String searchDirForFile(String dir, String fileName) {
    File[] files = new File(dir).listFiles();
    for(File f:files) {
        if(f.isDirectory()) {
            String loc = searchDirForFile(f.getPath(), fileName);
            if(loc != null)
                return loc;
        }
        if(f.getName().equals(fileName))
            return f.getPath();
    }
    return null;
}

Ответ 8

Используя функции Java 8+, мы можем написать код в нескольких строках:

protected static Collection<Path> find(String fileName, String searchDirectory) throws IOException {
    try (Stream<Path> files = Files.walk(Paths.get(searchDirectory))) {
        return files
                .filter(f -> f.getFileName().toString().equals(fileName))
                .collect(Collectors.toList());

    }
}

Files.walk возвращает Stream<Path> который "идет по дереву файлов, внедренному в" заданный searchDirectory. Чтобы выбрать нужные файлы, в Stream files применяется только фильтр. Он сравнивает имя файла Path с данным fileName.

Обратите внимание, что для документации Files.walk требуется

Этот метод должен использоваться в заявлении try-with-resources или аналогичной структуре управления, чтобы гарантировать, что потоковые открытые каталоги будут закрыты немедленно после завершения операций потока.

Я использую try-resource-statement.


Для расширенных поисков альтернативой является использование PathMatcher:

protected static Collection<Path> find(String searchDirectory, PathMatcher matcher) throws IOException {
    try (Stream<Path> files = Files.walk(Paths.get(searchDirectory))) {
        return files
                .filter(matcher::matches)
                .collect(Collectors.toList());

    }
}

Пример использования файла для поиска определенного файла:

public static void main(String[] args) throws IOException {
    String searchDirectory = args[0];
    String fileName = args[1];
    PathMatcher matcher = FileSystems.getDefault().getPathMatcher("regex:.*" + fileName);
    Collection<Path> find = find(searchDirectory, matcher);
    System.out.println(find);
}

Подробнее об этом: Учебник Oracle Finding Files