Как вы напишете java-функцию boolean sameContent(Path file1,Path file2)
, которая определяет, указывают ли эти два пути на файлы, которые хранят один и тот же контент? Конечно, во-первых, я бы проверял, одинаковы ли размеры файлов. Это необходимое условие для хранения одного и того же содержимого. Но тогда я хотел бы послушать ваши подходы. Если два файла хранятся на одном жестком диске (как и в большинстве моих случаев), это, вероятно, не самый лучший способ перепрыгнуть слишком много раз между этими двумя потоками.Определите, сохраняются ли два файла одного и того же контента
ответ
This должно помочь вам с вашей проблемой:
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);
}
}
Именно то, что FileUtils.contentEquals
метод Apache Commons IO делает и АФИ here.
Попробуйте что-то вроде:
File file1 = new File("file1.txt");
File file2 = new File("file2.txt");
boolean isTwoEqual = FileUtils.contentEquals(file1, file2);
Это следующие проверки перед тем, как выполнить сравнение:
- существование как файлы
- Оба файла, которые передаются должны быть файл тип, а не каталог.
- Длина в байтах не должна быть одинаковой.
- Оба - разные файлы, а не одно и то же.
- Затем сравните содержимое.
Чтобы добавить значение, я обнаружил, что 'FileUtils.contentEqualsIgnoreEOL' может предложить удобство для менее строгих утверждений. – CloudyTrees
Если вы не хотите использовать какие-либо внешние библиотеки, а затем просто читать файлы в байтовые массивы и сравнить их (не будет работать заранее Java-7):
byte[] f1 = Files.readAllBytes(file1);
byte[] f2 = Files.readAllBytes(file2);
с помощью Arrays.equals ,
Если файлы большие, то вместо того, чтобы считывать все файлы в массивы, вы должны использовать BufferedInputStream
и читать файлы по куску, как описано here.
Я хочу, чтобы моя программа также работала с большими файлами. Это может привести к OutOfMemoryError - если массив требуемого размера не может быть выделен, например, размер файла больше 2 ГБ. Редактировать: Извините, я только что видел ваше замечание о работе с большими файлами. –
Правда. Вот почему я включил ссылку на страницу SO, в которой упоминается использование BufferedInputStream и чтение chunk-by-chunk, а не весь файл. Нет никаких дублирующих ответов, которые уже присутствуют в SO. –
Если файлы малы, вы можете считывать их как в память, так и сравнивать массивы байтов.
Если файлы невелики, вы можете либо вычислить хеши их содержимого (например, 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;
}
Не можете ли вы просто обернуть входные потоки в 'BufferedInputStream'? Тогда метод будет таким же эффективным, как если бы вы использовали 'read (byte [])', но без сложности, не так ли? – aioobe
@aioobe Да, мы могли бы. Причина, по которой я использовал байтовое сравнение, заключается в том, что метод 'read (byte [])' не гарантированно полностью считывает переданный массив байтов (javadoc говорит _ "он читает до' bytes.length' _ _) , Если источником базового потока является файл, текущие реализации будут читать полный массив, но для этого нет никакой гарантии. И код, который должным образом обрабатывает чтение без полного массива, будет более сложным и привлечет внимание из принципа, который пытается показать мой snipplet кода. – icza
Я понимаю это, но то, что я пытаюсь сказать, заключается в том, что вы избегаете * без * этой сложности, используя «BufferedInputStream» (пока еще достигаете эффективности). – aioobe
У меня был сценарий, в котором я должен был сравнить любые два файла (видео/изображения/что угодно). Я пошел вперед, вычисляя 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);
Это крайне неэффективно –
@ AndyBrown Было бы здорово, если бы вы предложили мне эффективный способ сравнить любые два типа файлов (видео, изображения, txt и т. Д.). Заранее спасибо! –
Поскольку вы уже читаете весь поток байтов, почему бы просто не проверить байты байтом? – Panayotis
- 1. md5sum разные значения для одного и того же контента
- 2. Два процесса открытия одного и того же файла для записи
- 3. Почему Zipping одного и того же контента дважды дает два файла с разными SHA1?
- 4. C - Два процесса чтения одного и того же файла
- 5. два атрибута одного и того же лица
- 6. Два экземпляра одного типа для одного и того же типа
- 7. Галерея намерений для сохранения одного и того же контента?
- 8. Создайте английские версии одного и того же контента на Drupal?
- 9. Могу ли я выполнить два разных класса из одного и того же файла jar?
- 10. Могут ли два процесса считываться из одного и того же текстового файла одновременно без ошибок?
- 11. Возможно ли иметь два файла перевода для одного и того же языка?
- 12. Сохранение одного и того же изображения на два отдельных поля?
- 13. Файл hash: Изменяется ли он для одного и того же контента, но в другом порядке?
- 14. Определите, является ли данное число суммой одного и того же григорианского и хиджринского года?
- 15. Хорошо запустить несколько экземпляров одного и того же исполняемого файла?
- 16. CSS Два разных стиля для одного и того же поля
- 17. Суммировать два свойства одного и того же узла в Cypher
- 18. два разных синхронизированных метода одного и того же объекта?
- 19. два владельца для того же файла XIB
- 20. Сравните два пароли BCRYPTed для одного и того же источника
- 21. Как проверить два экземпляра одного и того же объекта?
- 22. Определенный тип файла mime для одного и того же файла
- 23. Дразнящий переменную, когда есть два одного и того же типа
- 24. Два входа для одного и того же значения в Shiny
- 25. Сравнить два файла контента
- 26. ActionResult для того же контента
- 27. Обработка индекса и index.php как одного и того же файла
- 28. Два предиката для одного и того же имущества в iOS
- 29. Рельсы отображают два модала с одного и того же вида
- 30. Два экземпляра одного и того же приложения прикосновения Сенча
Размер может отличаться, а также для того же содержания. В зависимости от нескольких факторов. Если вы действительно хотите сравнить контент, то простая проверка - сделать контрольную сумму обоих файлов и сравнить их. Вы можете использовать md5 в байтах файлов. Также можно использовать сравнение байтов. –