怎么用Java比较两个文件夹下所以图片是否相同呢?

yy499121268 2021-02-24 04:47:40
例如有两个文件夹A和B,两个文件夹分别有100张PNG的图片,图片的编号都是0-100,请问如何去比较两个文件夹里对应编号的图片是否相同呢,也就是A文件夹下的01.png和B文件夹下的01.png相比较,以此类推02.png和02.png比较...请问各位大佬用Java代码怎么实现呢?
...全文
2459 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
可乐罐 2021-03-17
  • 打赏
  • 举报
回复
感觉从文件名称、文件大小、选取文件随机采样内容字节数据的方式,应该能过滤大部分不同的情况。最后全文是否存在差异,还可以考虑参照校验位的处理办法。虽然每个字节比较最严谨,但个人感觉太极端了。
m0_55844471 2021-03-07
  • 打赏
  • 举报
回复
很厉害的样子啊
flybirding10011 2021-03-02
  • 打赏
  • 举报
回复
引用 27 楼 兔子兔兔兔 的回复:
[quote=引用 4 楼 yy499121268 的回复:][quote=引用 1 楼 qybao 的回复:]这个有点。。。 比如,A文件夹的01.png缩小80%,然后存到B文件夹的01.png,它们算不算相同? 用二进制方式把文件读入byte数组,比较byte数组的内容是否相同
这个不用担心 每张图片的此村大小都是一样的 单个图片比较已经搞定了 现在的问提是怎样去循环遍历让01和01比较 02和02比较这样把每一张图片都比一边 目前卡在这个位置了 有大老有思路吗 能用代码举个例子吗?[/quote] hash类算法不行吗?[/quote]
flybirding10011 2021-03-02
  • 打赏
  • 举报
回复
引用 4 楼 yy499121268 的回复:
[quote=引用 1 楼 qybao 的回复:]这个有点。。。 比如,A文件夹的01.png缩小80%,然后存到B文件夹的01.png,它们算不算相同? 用二进制方式把文件读入byte数组,比较byte数组的内容是否相同
这个不用担心 每张图片的此村大小都是一样的 单个图片比较已经搞定了 现在的问提是怎样去循环遍历让01和01比较 02和02比较这样把每一张图片都比一边 目前卡在这个位置了 有大老有思路吗 能用代码举个例子吗?[/quote] hash类算法不行吗?
Yx2020 2021-03-01
  • 打赏
  • 举报
回复
比文件大小?>?>
从入门to入万 2021-02-27
  • 打赏
  • 举报
回复
引用 8 楼 Francis.Sun 的回复:
public class FileTest { public static void main(String[] args) throws IOException { File file = new File("F:\\workspace\\soa-adm\\dev_soa_adm\\soa-adm-master\\soa-adm-portal\\src\\main\\resources\\static\\images\\donate_qrcode.png"); File file1 = new File("F:\\workspace\\soa-adm\\dev_soa_adm\\soa-adm-master\\soa-adm-portal\\src\\main\\resources\\static\\images\\donate_qrcode - 副本.png"); try { FileInputStream inputStream = new FileInputStream(file); FileInputStream inputStream1 = new FileInputStream(file1); boolean flag = false; byte c =(byte)inputStream.read(); byte c1 = (byte) inputStream1.read(); System.out.println(c); while ( c != -1 && c1!= -1){ c =(byte)inputStream.read(); c1 =(byte)inputStream1.read(); if(c1 != c){ flag = true; } } if(flag){ System.out.println("图片不相等"); }else { System.out.println("图片相等"); } } catch (FileNotFoundException e) { e.printStackTrace(); } } }
这个方法是可以
yyxgs 2021-02-27
  • 打赏
  • 举报
回复
KeepSayingNo 2021-02-27
  • 打赏
  • 举报
回复
应该是比较流
a1767028198 2021-02-26
  • 打赏
  • 举报
回复
看了下回复,只有hash靠谱点,你只要比较文件内容的话,直接对比md5值就行了 ps:有些地方下载软件,如果你担心文件被篡改的话,提供了文件的md5值,自己去校验就行了
冰思雨 2021-02-26
  • 打赏
  • 举报
回复
无非就是遍历文件夹的实现方案。 最简单的就是递归调用。
import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;

public class FileCompare {

    static final int BufferSize = 32 * 1024;

    interface ComparedHandler {
        void onCompared(File f1, File f2, boolean equal);
    }

    public static void main(String[] args) {
        final String path1 = "/path/a";
        final String path2 = "/path/b";
        doCompare(new File(path1), new File(path2), (File f1, File f2, boolean equal)->{
            //TODO 处理比较结果。
            System.out.println(String.format("文件 %s : %s , %s", equal?"相同":"不同", f1.getPath(), f2.getPath()));
        });
    }

    private static void doCompare(File f1, File f2, ComparedHandler handler) {
        if (f1.exists() && f2.exists()) {
            // 只比较同名的目录和文件
            if (f1.isDirectory() && f2.isDirectory()) { 
                Set<String> dn1 = Arrays.stream(f1.listFiles(f->f.isDirectory())).map(f->f.getName()).collect(Collectors.toSet());
                Set<String> dn2 = Arrays.stream(f2.listFiles(f->f.isDirectory())).map(f->f.getName()).collect(Collectors.toSet());
                dn1.retainAll(dn2);//两个集合的交集
                for (String name : dn1) {
                    doCompare(new File(f1, name), new File(f2, name), handler);
                }
                Set<String> fn1 = Arrays.stream(f1.listFiles(f->f.isFile())).map(f->f.getName()).collect(Collectors.toSet());
                Set<String> fn2 = Arrays.stream(f2.listFiles(f->f.isFile())).map(f->f.getName()).collect(Collectors.toSet());
                fn1.retainAll(fn2);//两个集合的交集
                for (String name : fn1) {
                    doCompare(new File(f1, name), new File(f2, name), handler);
                }
            } else if (f1.isFile() && f2.isFile()) {
                if (f1.length() == f2.length()) {
                    if (f1.length() <= BufferSize) { // 小文件的数据比较
                        byte[] d1 = new byte[(int)f1.length()];
                        byte[] d2 = new byte[(int)f2.length()];
                        try (FileInputStream fis1 = new FileInputStream(f1);
                             FileInputStream fis2 = new FileInputStream(f2)) {
                            fis1.read(d1);
                            fis2.read(d2);
                            handler.onCompared(f1, f2, Arrays.equals(d1, d2));
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    } else { // 大文件的数据比较
                        try (RandomAccessFile raf1 = new RandomAccessFile(f1, "r");
                             RandomAccessFile raf2 = new RandomAccessFile(f2, "r")){
                            FileChannel ch1 = raf1.getChannel();
                            FileChannel ch2 = raf2.getChannel();
                            long length = f1.length();
                            long position = 0;
                            boolean equal = true;
                            for(int bufferSize = 0; position < length; position += bufferSize) {
                                bufferSize = Math.min(BufferSize , (int)(length-position));
                                MappedByteBuffer buf1 = ch1.map(FileChannel.MapMode.READ_ONLY, position, bufferSize);
                                MappedByteBuffer buf2 = ch2.map(FileChannel.MapMode.READ_ONLY, position, bufferSize);
                                if (!buf1.equals(buf2)) {
                                    equal = false;
                                    break;
                                }
                            }
                            handler.onCompared(f1, f2, equal);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                } else {
                    handler.onCompared(f1, f2, false);
                }
            } 
        }
    }
}
文件数据的比较,还得是二进制数据的比较。 不太清楚实际的图片大小,如果都是小文件的话,可以直接全部读取到内存当中进行比较。 大文件(比如视频文件)可以使用内存映射形式的缓存进行比较,效率要高。 想进一步提升效率,可以考虑使用多线程,但是,效果可能不会太明显,因为瓶颈还是在IO访问上面。
qq_39936465 2021-02-26
  • 打赏
  • 举报
回复
引用 4 楼 yy499121268 的回复:
[quote=引用 1 楼 qybao 的回复:]这个有点。。。 比如,A文件夹的01.png缩小80%,然后存到B文件夹的01.png,它们算不算相同? 用二进制方式把文件读入byte数组,比较byte数组的内容是否相同
这个不用担心 每张图片的此村大小都是一样的 单个图片比较已经搞定了 现在的问提是怎样去循环遍历让01和01比较 02和02比较这样把每一张图片都比一边 目前卡在这个位置了 有大老有思路吗 能用代码举个例子吗?[/quote] 首先图片文件都是其实就是保存的像数点的信息,其实不用管图片的形状,只要考虑像数点的颜色是否一直就行了。 BufferedImage getHeigt getWidth 先获取图片像数, 然后通过 getRGB(int x int y)获取每个像数点的颜色,然后保存到一个list中,比较2个图片的list,如果某个像数点颜色不同就说明2张图片不一致
洛阳泰山 2021-02-26
  • 打赏
  • 举报
回复
一楼说的这种情况,感觉挺复杂的,这种情况是不是比较每一个的图片的像素相似度
一只三黄鸡 2021-02-26
  • 打赏
  • 举报
回复
按步骤来啊,先比较文件夹大小,大小一致再比较文件数量,文件数量一致再比较对应文件大小,对应文件大小一致 再比较文件hash。 这样前面只要有一个不满足就直接判断不一致了,可能效率会高点
maggieneedsahug 2021-02-26
  • 打赏
  • 举报
回复
我不太记得java了,不过如果两个文件夹中都是一百张图片,大小又一样,可不可以直接对文件夹取哈希然后比对
冰思雨 2021-02-26
  • 打赏
  • 举报
回复
引用 20 楼 a1767028198 的回复:
看了下回复,只有hash靠谱点,你只要比较文件内容的话,直接对比md5值就行了 ps:有些地方下载软件,如果你担心文件被篡改的话,提供了文件的md5值,自己去校验就行了
如果只比较MD5码的话,有极小的概率会出现问题。 这句话怎么理解呢? 相同文件的MD5值一定相同,这个是毫无疑问的,但是,不同文件会不会存在相同的MD5值呢?答案是肯定的,只是概率很小而已。 MD5码从某种意义上可以代表文件的某种数据特征,是文件的特征码。当你更改文件数据后,会导致数据特征发生变化,从而引起MD5值产生变化,但是,这种情况不是百分之百发生的,存在一定的几率,当你修改数据(删除,添加也算在内)后,MD5码没有发生变化的情况。 那么,MD5码的作用到底在哪儿呢? 不同MD5码对应的文件,数据一定是不相同的。 换句话说: 我们可以通过MD5码来判断文件的不同,却不能使用MD5码来判断文件的相同。 因为,相同MD5码的文件,数据有可能会不同;不同MD5码的文件,数据一定不同。 判断数据完全相同,还是要进行二进制数据的逐个比较才比较靠谱。 当然,如果文件的MD5码已经提前算出来了,可以用它加速比较过程。可以先排除MD5不同的情况,MD5码不同,文件一定不同。
hbhbhbhbhb1021 2021-02-25
  • 打赏
  • 举报
回复
改一下

package test;

import java.io.File;
import java.util.*;

public class Tester {
    public static void main(String[] args) {
        Tester tester=new Tester();
         Map<String, String> filesNameMap2 = tester.getFilesNameMap("xxx");
         Map<String, String> filesNameMap1 = tester.getFilesNameMap("xxx");
        for (String fileName:filesNameMap1.keySet()
             ) {
            if(filesNameMap2.containsKey(fileName)){
                //比较
            }else{
                System.out.println("不相等:"+fileName);
            }
        }
    }

    public  Map<String,String> getFilesNameMap(String filePath){
        File file=new File(filePath);
        String[] filesName = file.list();
        Map<String, String> map=new HashMap<String, String>();
        if(filesName==null)return map;
        for(String eachFile:filesName){
            map.put(eachFile,eachFile);
        }

        System.out.println(filesName.length);
        return map;
    }
}
hbhbhbhbhb1021 2021-02-25
  • 打赏
  • 举报
回复
顺便问下,这里比较两张图片是否一致的具体算法是通过聚类算法完成的?
hbhbhbhbhb1021 2021-02-25
  • 打赏
  • 举报
回复
楼主要的是不是只是遍历两个文件夹啊,下面的代码是以一个文件夹为基准,基准文件夹少了是看不出来的,你再改一改吧。 不过觉得这个需求有点怪,类似文件的版本控制了,如果这台服务器上还有其他业务很容易挂掉的,有没有可能通过其他手段控制下呢
package test;

import java.io.File;
import java.util.*;

public class Tester {
    public static void main(String[] args) {
        Tester tester=new Tester();
         Map<String, String> filesNameMap2 = tester.getFilesNameMap("xxx");//XXX是文件路径
         Map<String, String> filesNameMap1 = tester.getFilesNameMap("xxx");
        for (String fileName:filesNameMap1.keySet()
             ) {
            if(filesNameMap2.containsKey(fileName)){
                //比较
            }else{
                System.out.println("不相等:"+fileName);
            }
        }
    }

    public  Map<String,String> getFilesNameMap(String filePath){
        File file=new File(filePath);
        File[] files = file.listFiles();
        Map<String, String> map=new HashMap<String, String>();
        if(files==null)return map;
        for(File eachFile:files){
            map.put(eachFile.getName(),eachFile.getName());
        }

        System.out.println(files.length);
        return map;
    }
}
Francis.Sun 2021-02-25
  • 打赏
  • 举报
回复
public class FileTest { public static void main(String[] args) throws IOException { File file = new File("F:\\workspace\\soa-adm\\dev_soa_adm\\soa-adm-master\\soa-adm-portal\\src\\main\\resources\\static\\images\\donate_qrcode.png"); File file1 = new File("F:\\workspace\\soa-adm\\dev_soa_adm\\soa-adm-master\\soa-adm-portal\\src\\main\\resources\\static\\images\\donate_qrcode - 副本.png"); try { FileInputStream inputStream = new FileInputStream(file); FileInputStream inputStream1 = new FileInputStream(file1); boolean flag = false; byte c =(byte)inputStream.read(); byte c1 = (byte) inputStream1.read(); System.out.println(c); while ( c != -1 && c1!= -1){ c =(byte)inputStream.read(); c1 =(byte)inputStream1.read(); if(c1 != c){ flag = true; } } if(flag){ System.out.println("图片不相等"); }else { System.out.println("图片相等"); } } catch (FileNotFoundException e) { e.printStackTrace(); } } }
Francis.Sun 2021-02-25
  • 打赏
  • 举报
回复
我觉得可以用字节流流读取,然后读取出来的是二进制数字,就可以直接比较了
加载更多回复(9)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧