Подтвердить что ты не робот

Определите, сохраняет ли два файла один и тот же контент

Как вы напишете java-функцию boolean sameContent(Path file1,Path file2), которая определяет, указывают ли два указанных пути на файлы, которые хранят один и тот же контент? Конечно, во-первых, я бы проверял, одинаковы ли размеры файлов. Это необходимое условие для хранения одного и того же содержимого. Но тогда я хотел бы послушать ваши подходы. Если два файла хранятся на одном жестком диске (как и в большинстве моих случаев), это, вероятно, не самый лучший способ перепрыгнуть слишком много раз между двумя потоками.

4b9b3361

Ответ 1

Именно то, что метод FileUtils.contentEquals для Apocal commons IO делает, а api здесь.

Попробуйте что-то вроде:

File file1 = new File("file1.txt");
File file2 = new File("file2.txt");
boolean isTwoEqual = FileUtils.contentEquals(file1, file2);

Перед выполнением сравнения выполняются следующие проверки:

  • существование обоих файлов
  • Оба передаваемых файла должны иметь тип файла, а не каталог.
  • длина в байтах не должна быть одинаковой.
  • Оба - разные файлы, а не одно и то же.
  • Затем сравните содержимое.

Ответ 2

Если вы не хотите использовать какие-либо внешние библиотеки, просто прочитайте файлы в байтовые массивы и сравните их (не будет работать до Java-7):

byte[] f1 = Files.readAllBytes(file1);
byte[] f2 = Files.readAllBytes(file2);

с помощью Arrays.equals.

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

Ответ 3

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

Если файлы невелики, вы можете либо вычислить хэши их содержимого (например, MD5 или SHA-1) один за другим и сравнить хэши (но это все еще оставляет очень мало шансов на ошибку), либо вы могут сравнивать их содержимое, но для этого вам все равно придется читать потоки, чередующиеся.

Вот пример:

boolean sameContent(Path file1, Path file2) throws IOException {
    final long size = Files.size(file1);
    if (size != Files.size(file2))
        return false;

    if (size < 4096)
        return Arrays.equals(Files.readAllBytes(file1), Files.readAllBytes(file2));

    try (InputStream is1 = Files.newInputStream(file1);
         InputStream is2 = Files.newInputStream(file2)) {
        // Compare byte-by-byte.
        // Note that this can be sped up drastically by reading large chunks
        // (e.g. 16 KBs) but care must be taken as InputStream.read(byte[])
        // does not neccessarily read a whole array!
        int data;
        while ((data = is1.read()) != -1)
            if (data != is2.read())
                return false;
    }

    return true;
}

Ответ 4

Это должно помочь вам решить вашу проблему:

package test;

import java.io.File;
import java.io.IOException;

import org.apache.commons.io.FileUtils;

public class CompareFileContents {

    public static void main(String[] args) throws IOException {

        File file1 = new File("test1.txt");
        File file2 = new File("test2.txt");
        File file3 = new File("test3.txt");

        boolean compare1and2 = FileUtils.contentEquals(file1, file2);
        boolean compare2and3 = FileUtils.contentEquals(file2, file3);
        boolean compare1and3 = FileUtils.contentEquals(file1, file3);

        System.out.println("Are test1.txt and test2.txt the same? " + compare1and2);
        System.out.println("Are test2.txt and test3.txt the same? " + compare2and3);
        System.out.println("Are test1.txt and test3.txt the same? " + compare1and3);
    }
}

Ответ 5

Начиная с Java 12 существует метод Files.mismatch, который возвращает -1 если нет несоответствия в содержимом файлов. Таким образом, функция будет выглядеть следующим образом:

private static boolean sameContent(Path file1, Path file2) throws IOException {
    return Files.mismatch(file1, file2) == -1;
}

Ответ 6

У меня был сценарий, где мне приходилось сравнивать любые два файла (видео/изображения/все). Я начал вычислять md5 для двух файлов и сравнивая их. Он работал нормально.

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5EncoderUtility {
    public String encodeToMd5(String filePath) {

        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("SHA1");
        } catch (NoSuchAlgorithmException e1) {
            e1.printStackTrace();
        }
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(filePath);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        byte[] dataBytes = new byte[1024];

        int nread = 0;

        try {
            while ((nread = fis.read(dataBytes)) != -1) {
                md.update(dataBytes, 0, nread);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        byte[] mdbytes = md.digest();

        // convert the byte to hex format
        StringBuffer sb = new StringBuffer("");
        for (int i = 0; i < mdbytes.length; i++) {
            sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
        }

        System.out.println("Digest(in hex format):: " + sb.toString());
        return sb.toString();
    }
}

public class FileCompareUtility {
    MD5EncoderUtility md5EncoderUtil = new MD5EncoderUtility();

    public boolean compare2Files(String actualFilePath, String expectedFilePath) {
        if ((md5EncoderUtil.encodeToMd5(actualFilePath)).equals(md5EncoderUtil.encodeToMd5(expectedFilePath))) {
            System.out.println("The files- "+actualFilePath+" and "+expectedFilePath+" are same");
            return true;
        } else {
            System.out.println("The files- "+actualFilePath+" and "+expectedFilePath+" are NOT same");
            return false;
        }
    }

}

И может быть вызван следующим образом:

        String actualFileComparePath = "D:/Videos/test.mp4";
        String expectedFileComparePath = "D:/Videos/test2.mp4";

// This will compare any types of files- here video.Eg-Video
        fileCompareUtil.compare2Files(actualFileComparePath, expectedFileComparePath);

Ответ 7

package test;  

      import org.junit.jupiter.api.Test;

      import java.io.IOException;
      import java.nio.file.FileSystems;
      import java.nio.file.Files;
      import java.nio.file.Path;

import static org.junit.Assert.assertEquals;

public class CSVResultDIfference {

   @Test
   public void csvDifference() throws IOException {
       Path file_F = FileSystems.getDefault().getPath("C:\\Projekts\\csvTestX", "yolo2.csv");
       long size_F = Files.size(file_F);
       Path file_I = FileSystems.getDefault().getPath("C:\\Projekts\\csvTestZ", "yolo2.csv");
       long size_I = Files.size(file_I);
       assertEquals(size_F, size_I);

   }
}

у меня это сработало :)