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