Как удалить дубликаты файлов с тем же именем, но с другим расширением? - PullRequest
0 голосов
/ 04 июля 2018

У меня есть большое количество изображений в каталоге. Проблема с некоторыми изображениями состоит в том, что они имеют дубликаты с тем же именем, но с разным расширением, например image1.jpg, image1.jpeg, image1.png, которые представляют собой одинаковые изображения, с одинаковыми именами, но с разными расширениями. Как я могу найти и удалить эти дубликаты, используя Java? Существует множество инструментов для поиска дубликатов, но я не могу найти какой-либо инструмент или скрипт для этой конкретной проблемы. Любая помощь будет принята с благодарностью.

Ответы [ 3 ]

0 голосов
/ 04 июля 2018

Единственный способ добиться этого, imho, - создать вспомогательный класс:

    public class FileUtil {
    String fileName;
    File file;
    boolean delete = true;


    public FileUtil(String fileName, File file) {
        super();
        this.fileName = fileName.substring(0, fileName.indexOf("."));
        this.file = file;
    }

    public String getFileName() {
        return fileName;
    }
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }
    public File getFile() {
        return file;
    }
    public void setFile(File file) {
        this.file = file;
    }
    public boolean isDelete() {
        return delete;
    }
    public void setDelete(boolean delete) {
        this.delete = delete;
    }

    @Override
    public String toString() {
        return "FileUtil [fileName=" + fileName + ", file=" + file + ", delete=" + delete + "]";
    }

}

тогда вы можете использовать это для сбора и удаления ваших предметов:

try (Stream<Path> paths = Files.walk(Paths.get("c:/yourPath/"))) {
        List<FileUtil> listUtil = new ArrayList<FileUtil>();

        paths
            .filter(Files::isRegularFile)
            .map(filePath -> filePath.toFile())
            .collect(Collectors.toList())
            .forEach(file -> listUtil.add(new FileUtil(file.getName(), file)));

        Map<String, List<FileUtil>> collect = listUtil.stream()
                .collect(Collectors.groupingBy(FileUtil::getFileName));

        for(String key : collect.keySet() ) {
            List<FileUtil> list = collect.get(key);
            if(list.size() > 1) {
                list.stream().findFirst().ifPresent(f -> f.setDelete(false));

                list.stream()
                    .filter(fileUtil -> fileUtil.isDelete())
                    .forEach(fileUtil -> fileUtil.getFile().delete());
            }
        }


    } catch (IOException e) {
        e.printStackTrace();
    } 

Таким образом, я сохраняю случайный элемент, если вы предпочитаете, вы можете изменить класс так, чтобы он содержал только то расширение, которое вам нужно, например .png

Надеюсь, это поможет:)

0 голосов
/ 04 июля 2018

Вот MCVE :

В этом примере реализуется Set для автоматического удаления дубликатов изображений путем предоставления только пути к папке / каталогу, в котором находятся изображения (, просто другая идея, чтобы показать другие доступные параметры и как использовать функции OO на Java )

import java.io.File;
import java.util.HashSet;
import java.util.Set;

public class DuplicateRemover {

    // inner class to represent an image
    class Image{
        String path; // the absolute path of image file as a String

        // constructor
        public Image(String path) {
            this.path = path;
        }       

        @Override
        public boolean equals(Object o) {
            if(o instanceof Image){
                // if both base names are equal -> delete the old one
                if(getBaseName(this.path).equals(getBaseName(((Image)o).path))){
                    File file = new File(this.path);
                    return file.delete();
                }
            }
            return false;
        }

        @Override
        public int hashCode() {
            return 0; // in this case, only "equals()" method is considered for duplicate check
         } 

         /**
          * This method to get the Base name of the image from the path
          * @param fileName
          * @return
          */
        private String getBaseName(String fileName) {
            int index = fileName.lastIndexOf('.'); 
            if (index == -1) { return fileName; } 
            else { return fileName.substring(0, index); }
         }
    }


    Set<Image> images; // a set of image files

    //constructor
    public DuplicateRemover(){
        images = new HashSet<>();
    } 

    /**
     * Get the all the images from the given folder
     * and loop through all files to add them to the images set
     * @param dirPath
     */
    public void run(String dirPath){
        File dir = new File(dirPath);
        File[] listOfImages = dir.listFiles(); 
        for (File f : listOfImages){
            if (f.isFile()) { 
                images.add(new Image(f.getAbsolutePath()));
            }
        }
    }


    //TEST
    public static void main(String[] args) {
        String dirPath = "C:\\Users\\Yahya Almardeny\\Desktop\\folder";
        /* dir contains: {image1.png, image1.jpeg, image1.jpg, image2.png}       */
        DuplicateRemover dr = new DuplicateRemover();
        // the images set will delete any duplicate image from the folder
        // according to the logic we provided in the "equals()" method
        dr.run(dirPath); 

        // print what images left in the folder
        for(Image image : dr.images) {
            System.out.println(image.path);
        }

        //Note that you can use the set for further manipulation if you have in later
    }

}

Результат

C:\Users\Yahya Almardeny\Desktop\folder\image1.jpeg
C:\Users\Yahya Almardeny\Desktop\folder\image2.png
0 голосов
/ 04 июля 2018

Считайте все ваши файлы в List своего рода:

List<File> filesInFolder = Files.walk(Paths.get("\\path\\to\\folder"))
        .filter(Files::isRegularFile)
        .map(Path::toFile)
        .collect(Collectors.toList());

Затем просто переберите их и удалите, если файл не заканчивается желаемым расширением:

filesInFolder.stream().filter((file) -> (!file.toString().endsWith(".jpg"))).forEach((file) -> {
    file.delete();
});

Вы можете приспособить это к вашей конкретной потребности.

...