Dateien vergleichen

Status
Nicht offen für weitere Antworten.

The_S

Top Contributor
Hi,

ich möchte Dateien miteinander vergleichen und überprüfen, ob es sich hierbei um die selben Daten handelt. Eine Datei exakt mit einer anderen zu vergleichen ist nicht schwer (byte-weise lesen und vergleichen). Komplexer wird es allerdings, wenn man eine gewisse Toleranz einbauen möchte, also wenn die Dateien immernoch als identisch angesehen werden soll, auch wenn sie um einen bestimmten grad voneinander abweichen. Hier funktioniert ein Zeichenweiser vergleich natürlich nicht. Sollte nämlich in der einen Datei am Anfang ein byte fehlen, aber ansonsten identisch sein, würde dieser "Algorithmus" die beiden Dateien trotzdem als nicht identisch einstufen. Die einzige Lösung, die mir (bis jetzt) eingefallen ist, wäre das häppchenweise vergleichen der Dateien. Also beide Dateien einlesen, die eine in mehrere Stücke aufteilen und überprüfen ob dieses Stück auch in der anderen Datei vorkommt. Falls ja Position merken und ab dieser Position nach dem nächsten Stück suchen.

Das konnte ich auch schon umsetzen:

(Methode compareGoodwill, goodwillFact = Toleranz in Prozent, bufferSize die Größe der "Stücke")

Code:
package tools.io;

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

public class BinaryCompare {

	public boolean compareExactly(File one, File two) throws IOException {
		
		if (one.length()==two.length()) {
			FileInputStream fis1 = new FileInputStream(one);
			FileInputStream fis2 =new FileInputStream(two);
			int temp = 0;
			while ((temp = fis1.read()) != -1) {
				if (temp != fis2.read()) {
					return false;
				}
			}
			return true;
		}
		return false;
	}
	
	public boolean compareGoodwill(File one, File two, int goodwillFact, int bufferSize) throws IOException {
		
		if (one.length() < two.length()) {
			String temp = two.getAbsolutePath();
			two = new File(one.getAbsolutePath());
			one = new File(temp);
		}
		long diff = one.length() - two.length();
		if (diff > one.length() * goodwillFact / 100D) {
			System.out.println("Size does matter!");
			return false;
		}
		String[] parts  = createParts(readFile(one), bufferSize);
		StringBuilder str = new StringBuilder(readFile(two));
		int mismatch = 0;
		int pos = 0;
		int temp = 0;
		double maxMismatch = parts.length * goodwillFact / 100D;
		for (int i = 0; i < parts.length; i++) {
			System.out.println("1: " + System.currentTimeMillis());
			temp = str.indexOf(parts[i], pos);
			System.out.println("2: " + System.currentTimeMillis());
			if (temp != -1) {
				if ((temp - pos) / bufferSize + mismatch <= maxMismatch) { 
					pos = temp + bufferSize;
				}
				else {
					mismatch++;
					if (mismatch > maxMismatch) {
						System.out.println(mismatch + "/" + maxMismatch);
						return false;
					}
				}
			}
			else {
				mismatch++;
				if (mismatch > maxMismatch) {
					System.out.println(mismatch + "/" + maxMismatch);
					return false;
				}
			}
		}
		System.out.println(mismatch + "/" + maxMismatch);
		return true;
	}
	
	public int[] getOptimizedBufferRange(File file) {
		
		int[] range = new int[2];
		range[0] = (int)(file.length() * 0.04D / 100D);
		range[1] = (int)(file.length() * 0.14D / 100D);
		return range;
	}
	
	private String[] createParts(String str, int buffer) {
		
		String[] parts = null;
		if (str.length() % buffer == 0) {
			parts = new String[str.length() / buffer];
		}
		else {
			parts = new String[str.length() / buffer + 1];
		}
		for (int i = 0; i < parts.length; i++) {
			if (i * buffer + buffer > str.length()) {
				parts[i] = str.substring(i * buffer);
			}
			else {
				parts[i] = str.substring(i * buffer, i * buffer + buffer);
			}
		}
		return parts;
	}
	
	private String readFile(File file) throws IOException {
		
		StringBuilder build = new StringBuilder();
		FileInputStream fis = new FileInputStream(file);
		int temp = 0;
		while ((temp = fis.read()) != -1) {
			build.append((char)temp);
		}
		return build.toString();
	}
	
	public static void main(String[] args) throws IOException {
		
		BinaryCompare fc = new BinaryCompare();
		File one = new File("Z:\\BinaryCompareTest\\fahrplan.bmp");
		File two = new File("Z:\\BinaryCompareTest\\fahrplan2.bmp");
		int proz = 30;
		int oneR = fc.getOptimizedBufferRange(one)[0];
		int twoR = fc.getOptimizedBufferRange(one)[1];
		oneR = (oneR < 5 ? 5 : oneR);
		twoR = (twoR < 10 ? 10 : twoR);
		System.out.println(fc.compareExactly(one, two));
	//	System.out.println(fc.compareGoodwill(one, two, proz, 3));
		System.out.println(fc.compareGoodwill(one, two, proz, (oneR + twoR) / 2));
		System.out.println(fc.compareGoodwill(one, two, proz, oneR));
		System.out.println(fc.compareGoodwill(one, two, proz, twoR));
	}
}

Jetzt zu meinen Fragen:

1.) Kennt jemand eine bessere Methode (die ich auch halbwegs verstehe)?
2.) Hat jemand Verbesserungsvorschläge für diese Methode (Performance ist erstmal eher unwichtig)?

Das wars auch schon. Danke!
 
G

Guest

Gast
Ich weiss ja nicht obs dir weiterhilft, was mir dazu einfällt wäre es eine gewisse Anzahl Fehlern zu zu lassen, oder Fehler gewisse Wertigkeit zugeben. Ein Fehler ist zum Beispiel 1 Wert, ein anderer schwerwiegenderer Fehler wäre 5 Wert, und im gesamten darf die Summe aller Werte nen Schwellenwert nicht überschreiten.
 

The_S

Top Contributor
Also entweder missverstehe ich dich, oder du hast übersehen, dass das bereits eingebaut ist ;) . Falls ein Block/Stück nicht gefunden werden kann, oder sich in einem zu großen Abstand (der die maximale Abweichung sprengen würde) zum letzten Treffer befindet, wird ein Fehler hinzugerechnet. Am Ende wird dann überprüft ob die mitgegebene Kulanz überschritten wurde oder sich die Anzahl der Fehler im Rahmen befinden.
 

thE_29

Top Contributor
Wie wärs MD5 erstellen und den vergleichen?! ;)

Zuerst mal auf Größe der Datei abprüfen! Ist die nicht gleich, isses schon mal net gleich! Dann MD5 überprüfen ^^
 

The_S

Top Contributor
thE_29 hat gesagt.:
Wie wärs MD5 erstellen und den vergleichen?! ;)

Zuerst mal auf Größe der Datei abprüfen! Ist die nicht gleich, isses schon mal net gleich! Dann MD5 überprüfen ^^

Ja, das ist ja alles schön und gut, wird auch (zumindest die Größe überprüfen) bei der exakten Dateiübereinstimmung berücksichtigt.

Mein Hauptproblem ist aber der Vergleich mit einer bestimmten Toleranz. Da kann die Datei-Größe schonmal voneinander abweichen (momentan teste ich das erfolgreich an zwei geringfügig unterschiedlichen Excel-Sheets). Genauso hilft mir hier MD5 auch nicht weiter.

Aber schonma danke für eure Bemühungen.
 

thE_29

Top Contributor
Achso.. Wenn du das so vergleichen willst, wird es recht kompliziert..

Weil was ist wenn Datei2 einfach am Anfang 1 byte mehr hat!

So klappt nie ein byteweiser vergleich der 2 Dateien obwohl nur 1 byte mehr ist als beim anderen ^^
 

The_S

Top Contributor
@thE_29

evtl. würde es angebracht, wenn du meine posts auch mal komplett liest, bevor du wilde Spekulationen aufbringst ;) .

Ich habe bereits einen funktionierenden Alogrithmus entwickelt (code), der auch funktioniert wenn eine Datei größer als die andere ist. Die frage ist nur inwiefern das auch anders geht bzw. man diesen optimieren kann.

Bei Datentypen die komprimiert werden (wie JPG oder PNG) funktioniert der algo natürlich nicht, aber bei z. B. einem Word oder Exceldokument, bei welchem ein paar Worte/Sätze (je nach gesamtgröße) verändert wurden oder auch bei einem bmp (keine Kompression), bei dem ich einfach mal "Hallo" drüber geschrieben habe, funktioniert der Algorithmus.
 

TRunKX

Bekanntes Mitglied
Hmmm du müsstest die vorher überlegen wie groß die Abweichung seindarf.


sagen wir 1 Fehler auf 1000 vergleiche dann mach dir nen Zähler der bei 1 beginnt. Jeder Fehler wird gezählt und dann würde sich ne Abweichung von 0,1 oder weniger % nicht als abbruch bemerkbar machen.


Kannste dir dann durch Zählschleifen fertig machen. Was dann noch wichtig ist ist folgendes. Wenn ein Teil dazugekommen ist musst du dem Programm beibringen das er in beiden Dateien an dne nächsten gemeinsamen Punkt geht um von dort weiter zu suchen.
 

The_S

Top Contributor
Leutz ... ohne euch kritisieren zu wollen (bin ja auch echt für jede Hilfe dankbar), aber lest euch doch bitte mal den kompletten Thread durch. Alle 4 Posts von euch (1x gast, 2x thE_29 und 1x TRunKX) helfen mir kein Stück weiter. Für den Fall, dass ich mich einfach net richtig Ausgedrückt habe, hier nochmal die Lage in Kurzform:

Was ich möchte:

a) Verbesserungen für meinen bereits vorhandenen Algorithmus bezüglich oben genannter Problemstellung
b) Vorschlag für einen anderen, evtl. besseren Algorithmus für die oben genannte Problemstellung

Was ich habe:

- Einen Algorithmus um Dateien auf komplette Übereinstimmung zu überprüfen
- Einen Algorithmus um Dateien auf Übereinstimmung zu überprüfen, auch wenn sie sich geringfügig auf Byte-Ebene unterscheiden (inkl. größere/kleinere Dateien als die Ursprungsdatei)
 

sparrow

Top Contributor
Das GNUWerkzeug diff tut ja genau das und zeigt dir die Unterschiede zwischen den beiden Dateien an.
Vielleicht kann dir dessen Quellcode weiterhelfen?

Gruß
Sparrow
 

The_S

Top Contributor
Hm, danke erstmal für nen produktiven Beitrag ;) . Funktioniert diff nicht wie z. B. ein CVS-Repository? Also den kurz möglichsten Weg finden, um zwei Dateien aneinander anzupassen, sprich Änderungen in Textdateien aufzeigen? Weil ich brauche das primär für Binär- und nicht für Textdateien, was den eingesetzten Algorithmus doch ein bisschen mehr fordern sollte (für Textdateien hab ich den (oder zumindest einen ähnlichen) Algo schonmal nachprogrammiert).
 

The_S

Top Contributor
Aktualisierte Version des Quellcodes. Für Kritik und Anregugnen bin ich immernoch dankbar ;)

Code:
package tools.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Arrays;

public class BinaryCompare {

	private double maxMismatch = 0;
	private int mismatch = 0;
	
	public boolean compareExactly(File one, File two) throws IOException {
		
		if (one.length()==two.length()) {
			FileInputStream fis1 = new FileInputStream(one);
			FileInputStream fis2 =new FileInputStream(two);
			int temp = 0;
		 	while ((temp = fis1.read()) != -1) {
				if (temp != fis2.read()) {
					return false;
				}
			}
			return true;
		}
		return false;
	}
	
	public boolean compareGoodwill(File one, File two, int goodwillFact, int bufferSize, boolean moreGoodwill, boolean compareSorted) throws IOException {
		
		if (one.length() < two.length()) {
			String temp = two.getAbsolutePath();
			two = new File(one.getAbsolutePath());
			one = new File(temp);
		}
		long diff = one.length() - two.length();
		if (diff > one.length() * goodwillFact / 100D) {
			return false;
		}
		byte[] file = null;
		byte[][] parts = null;
		if (compareSorted) {
			file = readFile(one);
			Arrays.sort(file);
			parts = createParts(file, bufferSize);
			file = readFile(two);
			Arrays.sort(file);
		}
		else {
			parts = createParts(readFile(one), bufferSize);
			file = readFile(two);
		}
		if (moreGoodwill) {
			return compareMoreGoodwill(parts, file, goodwillFact, bufferSize);
		}
		return compareGoodwill(parts, file, goodwillFact, bufferSize);
	}
	
	public boolean compareGoodwill(byte[][] parts, byte[] file, int goodwillFact, int bufferSize) {
		
		maxMismatch = parts.length * goodwillFact / 100D;
		mismatch = 0;
		int pos = 0;
		int temp = 0;
		int lastBuf = (int)maxMismatch * bufferSize;
		for (int i = 0; i < parts.length; i++) {
			temp = myIndexOf(file, parts[i], pos, (int)(pos + lastBuf));
			if (temp != -1) {
				pos = temp + bufferSize;
			}
			else {
				mismatch++;
				lastBuf = (int)(maxMismatch - mismatch) * bufferSize;
				if (mismatch > maxMismatch) {
					return false;
				}
			}
		}
		return true;
	}
	
	public boolean compareMoreGoodwill(byte[][] parts, byte[] file, int goodwillFact, int bufferSize) {
		
		maxMismatch = parts.length * goodwillFact / 50D;
		mismatch = 0;
		int pos = 0;
		int temp = 0;
		int lastBuf = (int)maxMismatch / 2 * bufferSize;
		int[] notFound = new int[parts.length];
		for (int i = 0; i < parts.length; i++) {
			temp = myIndexOf(file, parts[i], pos, (int)(pos + lastBuf));
			if (temp != -1) {
				replaceRange(file, temp, temp + bufferSize, Byte.MIN_VALUE);
				pos = temp;
			}
			else {
				notFound[mismatch] = i;
				mismatch++;
				lastBuf = (int)(maxMismatch / 2 - mismatch) * bufferSize;
				if (mismatch > maxMismatch) {
					return false;
				}
			}
		}
		for (int i = mismatch - 1; i > -1; i--) {
			temp = myIndexOf(file, parts[notFound[i]], 0, file.length);
			if (temp != -1) {
				replaceRange(file, temp, temp + bufferSize, (byte)-1);
			}
			else {
				mismatch++;
				if (mismatch > maxMismatch) {
					return false;
				}
			}
		}
		return true;
	} 
	
	public int[] getOptimizedBufferRange(File file) {
		
		int[] range = new int[2];
		range[0] = (int)(file.length() * 0.04D / 100D);
		range[1] = (int)(file.length() * 0.14D / 100D);
		range[0] = range[0] < 5 ? 5 : range[0];
		range[1] = range[1] < 10 ? 10 : range[1];
		return range;
	}
	
	public byte[][] createParts(byte[] data, int buffer) {
		
		byte[][] parts = null;
		if (data.length % buffer == 0) {
			parts = new byte[data.length / buffer][buffer];
		}
		else {
			parts = new byte[data.length / buffer + 1][buffer];
		}
		for (int i = 0, k = 0; i < parts.length; i++) {
			for (int j = 0; j < parts[i].length; j++, k++) {
				if (k >= data.length) {
					parts[i][j] = -1;
				}
				else { 
					parts[i][j] = data[k];
				}
			}
		}
		return parts;
	}
	
	public byte[] readFile(File file) throws IOException {
		
		FileChannel fc = new FileInputStream(file).getChannel();
		ByteBuffer buff = ByteBuffer.allocate((int)file.length());
		fc.read(buff);
		return buff.array();
	}
	
	public int myIndexOf(byte[] file, byte[] target, int startPos, int endPos) {
		
		int tlength = target.length;
		int startInt = target[0];
		if (endPos > file.length) {
			endPos = file.length;
		}
		if (target.length > endPos - startPos) {
			return -1;
		}
		for (int i = 0, count = 0, pos = startPos - 1;pos + tlength < endPos;) {
			while(++pos + tlength < endPos && file[pos] != startInt);
			i = pos;
			count = 0;
			for (;count < tlength && file[i] == target[count];i++, count++);
			if (count == tlength) {
				return pos;
			}
		}
		return -1;
	}
	
	public void replaceRange(byte[] array, int start, int end, byte number) {
		
		for (int i = start; i < end; i++) {
			array[i] = number;
		}
	}
	
	public double getMaxMismatch() {
		return maxMismatch;
	}

	public void setMaxMismatch(double maxMismatch) {
		this.maxMismatch = maxMismatch;
	}

	public int getMismatch() {
		return mismatch;
	}

	public void setMismatch(int mismatch) {
		this.mismatch = mismatch;
	}

	public static void main(String[] args) throws IOException {
		
		BinaryCompare fc = new BinaryCompare();
		File one = new File("Z:\\BinaryCompareTest\\pic.bmp");
		File two = new File("Z:\\BinaryCompareTest\\pic2.bmp");
		int proz = 25;
		int oneR = fc.getOptimizedBufferRange(one)[0];
		int twoR = fc.getOptimizedBufferRange(one)[1];
		System.out.println("Sorted Goodwill");
		System.out.println(fc.compareGoodwill(one, two, proz, (oneR + twoR) / 2, false, true));
		System.out.println(fc.getMismatch() +"/" + fc.getMaxMismatch());
		System.out.println(fc.compareGoodwill(one, two, proz, oneR, false, true));
		System.out.println(fc.getMismatch() +"/" + fc.getMaxMismatch());
		System.out.println(fc.compareGoodwill(one, two, proz, twoR, false, true));
		System.out.println(fc.getMismatch() +"/" + fc.getMaxMismatch());
		System.out.println("Sorted more Goodwill");
		System.out.println(fc.compareGoodwill(one, two, proz, (oneR + twoR) / 2, true, true));
		System.out.println(fc.getMismatch() +"/" + fc.getMaxMismatch());
		System.out.println(fc.compareGoodwill(one, two, proz, oneR, true, true));
		System.out.println(fc.getMismatch() +"/" + fc.getMaxMismatch());
		System.out.println(fc.compareGoodwill(one, two, proz, twoR, true, true));
		System.out.println(fc.getMismatch() +"/" + fc.getMaxMismatch());
		System.out.println("Unsorted Goodwill");
		System.out.println(fc.compareGoodwill(one, two, proz, (oneR + twoR) / 2, false, false));
		System.out.println(fc.getMismatch() +"/" + fc.getMaxMismatch());
		System.out.println(fc.compareGoodwill(one, two, proz, oneR, false, false));
		System.out.println(fc.getMismatch() +"/" + fc.getMaxMismatch());
		System.out.println(fc.compareGoodwill(one, two, proz, twoR, false, false));
		System.out.println(fc.getMismatch() +"/" + fc.getMaxMismatch());
		System.out.println("Unsorted more Goodwill");
		System.out.println(fc.compareGoodwill(one, two, proz, (oneR + twoR) / 2, true, false));
		System.out.println(fc.getMismatch() +"/" + fc.getMaxMismatch());
		System.out.println(fc.compareGoodwill(one, two, proz, oneR, true, false));
		System.out.println(fc.getMismatch() +"/" + fc.getMaxMismatch());
		System.out.println(fc.compareGoodwill(one, two, proz, twoR, true, false));
		System.out.println(fc.getMismatch() +"/" + fc.getMaxMismatch());
	}
}
 

The_S

Top Contributor
So, ich mach dann mal weiter einen auf "Alleinunterhalter"

Code:
package tools.io;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;

public class BinaryCompare {

	private double maxMismatch = 0;
	private int mismatch = 0;
	private int maxFileSize = 5242880;
	
	private File firstFile = null;
	private File secondFile = null;
	
	private boolean compareBigFiles(File one, File two, int goodwillFact, int bufferSize, boolean moreGoodwill, boolean compareSorted) throws IOException {
		
		BufferedInputStream buffy = new BufferedInputStream(new FileInputStream(one));
		BufferedInputStream buffy2 = new BufferedInputStream(new FileInputStream(two));
		byte[] b1 = new byte[maxFileSize];
		byte[] b2 = new byte[maxFileSize];
		byte[][] parts = null;
		int plus = 0;
		int minus = 0;
		while ((buffy.read(b1) != -1) && (buffy2.read(b2) != -1)) {
			if (compareSorted) {
				Arrays.sort(b1);
				Arrays.sort(b2);
			}
			parts = createParts(b1, bufferSize);
			if (moreGoodwill) {
				if (compareMoreGoodwill(parts, b2, goodwillFact, bufferSize)) {
					plus++;
				}
				else {
					minus++;
				}
			}
			else {
				if (compareGoodwill(parts, b2, goodwillFact, bufferSize)) {
					plus++;
				}
				else {
					minus++;
				}
			}
		}
		maxMismatch = (plus + minus) * goodwillFact / 100;
		mismatch = minus;
		buffy.close();
		buffy2.close();
		if (minus < maxMismatch) {
			return true;
		}
		return false;
	}
	
	private ArrayList<File> listDir(File dir) {

		File[] files = dir.listFiles();
		ArrayList<File> f = new ArrayList<File>();
		if (files != null) {
			for (int i = 0; i < files.length; i++) {
				if (files[i].isDirectory()) {
					f.addAll(listDir(files[i]));
				}
				else {
					f.add(files[i]);
				}
			}
		}
		return f;
	}
	
	public ArrayList<File[]> compareFilesInDirectory (File dir, int goodwillFact, boolean moreGoodwill, boolean compareSorted) throws IOException {
		
		ArrayList<File[]> matches = new ArrayList<File[]>();
		ArrayList<File> files = listDir(dir);
		int size = files.size();
		int bufferSize = 0;
		byte[][] parts = null;
		byte[] buff = null;
		
		Collections.sort(files, new Comparator<File>() {
			public int compare(File one, File two) {
				if (one.length() > two.length()) {
					return 1;
				}
				return -1;
			}
		});
		
		for (int i = 0; i < size; i++) {
			System.out.println(i);
			setFirstFile(files.get(i));
			bufferSize = getMiddleBuffer(getFirstFile());
			if (getFirstFile().length() < getMaxFileSize()) {
				buff = readFile(getFirstFile());
				if (compareSorted) {
					Arrays.sort(buff);
				}
				parts = createParts(buff, bufferSize);
			}
			for (int j = i + 1; j < size; j++) {
				setSecondFile(files.get(j));
				if (getSecondFile().length() < getMaxFileSize()) {
					if ((getSecondFile().length() - getFirstFile().length()) > getFirstFile().length() * goodwillFact / 100D) {
						break;
					}
					buff = readFile(getSecondFile());
					if (compareSorted) {
						Arrays.sort(buff);
					}
					if (moreGoodwill) {
						if (compareMoreGoodwill(parts, buff, goodwillFact, bufferSize)) {
							matches.add(new File[] {getFirstFile(), getSecondFile()});
						}
					}
					else {
						if (compareGoodwill(parts, buff, goodwillFact, bufferSize)) {
							matches.add(new File[] {getFirstFile(), getSecondFile()});
						}
					}
				}
				else if (compareGoodwill(getFirstFile(), getSecondFile(), goodwillFact, bufferSize, false, false)) {
					matches.add(new File[] {files.get(i), files.get(j)});
				}
			}
		}
		return matches;
	}

	public boolean compareExactly(File one, File two) throws IOException {
		
		if (one.length()==two.length()) {
			FileInputStream fis1 = new FileInputStream(one);
			FileInputStream fis2 =new FileInputStream(two);
			int temp = 0;
		 	while ((temp = fis1.read()) != -1) {
				if (temp != fis2.read()) {
					fis1.close();
					fis2.close();
					return false;
				}
			}
		 	fis1.close();
			fis2.close();
			return true;
		}
		return false;
	}
	
	public boolean compareGoodwill(File one, File two, int goodwillFact, int bufferSize, boolean moreGoodwill, boolean compareSorted) throws IOException {
		
		if (one.length() < two.length()) {
			String temp = two.getAbsolutePath();
			two = new File(one.getAbsolutePath());
			one = new File(temp);
		}
		long diff = one.length() - two.length();
		if (diff > one.length() * goodwillFact / 100D) {
			return false;
		}
		if (one.length() > maxFileSize) {
			return compareBigFiles(one, two, goodwillFact, bufferSize, moreGoodwill, compareSorted);
		}
		byte[] file = null;
		byte[][] parts = null;
		if (compareSorted) {
			file = readFile(one);
			Arrays.sort(file);
			parts = createParts(file, bufferSize);
			file = readFile(two);
			Arrays.sort(file);
		}
		else {
			parts = createParts(readFile(one), bufferSize);
			file = readFile(two);
		}
		if (moreGoodwill) {
			return compareMoreGoodwill(parts, file, goodwillFact, bufferSize);
		}
		return compareGoodwill(parts, file, goodwillFact, bufferSize);
	}
	
	public boolean compareGoodwill(byte[][] parts, byte[] file, int goodwillFact, int bufferSize) {
		
		maxMismatch = parts.length * goodwillFact / 100D;
		mismatch = 0;
		int pos = 0;
		int temp = 0;
		int lastBuf = (int)maxMismatch * bufferSize;
		for (int i = 0; i < parts.length; i++) {
			temp = myIndexOf(file, parts[i], pos, (int)(pos + lastBuf));
			if (temp != -1) {
				pos = temp + bufferSize;
			}
			else {
				mismatch++;
				lastBuf = (int)(maxMismatch - mismatch) * bufferSize;
				if (mismatch > maxMismatch) {
					return false;
				}
			}
		}
		return true;
	}
	
	public boolean compareMoreGoodwill(byte[][] parts, byte[] file, int goodwillFact, int bufferSize) {
		
		maxMismatch = parts.length * goodwillFact / 50D;
		mismatch = 0;
		int pos = 0;
		int temp = 0;
		int lastBuf = (int)maxMismatch / 2 * bufferSize;
		int[] notFound = new int[parts.length];
		for (int i = 0; i < parts.length; i++) {
			temp = myIndexOf(file, parts[i], pos, (int)(pos + lastBuf));
			if (temp != -1) {
				replaceRange(file, temp, temp + bufferSize, Byte.MIN_VALUE);
				pos = temp;
			}
			else {
				notFound[mismatch] = i;
				mismatch++;
				lastBuf = (int)(maxMismatch / 2 - mismatch) * bufferSize;
				if (mismatch > maxMismatch) {
					return false;
				}
			}
		}
		for (int i = mismatch - 1; i > -1; i--) {
			temp = myIndexOf(file, parts[notFound[i]], 0, file.length);
			if (temp != -1) {
				replaceRange(file, temp, temp + bufferSize, (byte)-1);
			}
			else {
				mismatch++;
				if (mismatch > maxMismatch) {
					return false;
				}
			}
		}
		return true;
	}
	
	public int[] getOptimizedBufferRange(File file) {
		
		int[] range = new int[2];
		range[0] = (int)(file.length() * 0.04D / 100D);
		range[1] = (int)(file.length() * 0.14D / 100D);
		range[0] = range[0] < 5 ? 5 : range[0];
		range[1] = range[1] < 10 ? 10 : range[1];
		return range;
	}
	
	public int getMiddleBuffer(File file) {
		
		int i = (int)(file.length() * 0.07D / 100D);
		return i < 7 ? 7 : i;
	}
	
	public byte[][] createParts(byte[] data, int buffer) {
		
		byte[][] parts = null;
		if (data.length % buffer == 0) {
			parts = new byte[data.length / buffer][buffer];
		}
		else {
			parts = new byte[data.length / buffer + 1][buffer];
		}
		for (int i = 0, k = 0; i < parts.length; i++) {
			for (int j = 0; j < parts[i].length; j++, k++) {
				if (k >= data.length) {
					parts[i][j] = -1;
				}
				else { 
					parts[i][j] = data[k];
				}
			}
		}
		return parts;
	}
	
	public byte[] readFile(File file) throws IOException, OutOfMemoryError {
		
		FileChannel fc = new FileInputStream(file).getChannel();
		ByteBuffer buff = ByteBuffer.allocate((int)file.length());
		fc.read(buff);
		fc.close();
		return buff.array();
	}
	
	public int myIndexOf(byte[] file, byte[] target, int startPos, int endPos) {
		
		int tlength = target.length;
		int startInt = target[0];
		if (endPos > file.length) {
			endPos = file.length;
		}
		if (target.length > endPos - startPos) {
			return -1;
		}
		for (int i = 0, count = 0, pos = startPos - 1;pos + tlength < endPos;) {
			while(++pos + tlength < endPos && file[pos] != startInt);
			i = pos;
			count = 0;
			for (;count < tlength && file[i] == target[count];i++, count++);
			if (count == tlength) {
				return pos;
			}
		}
		return -1;
	}
	
	public void replaceRange(byte[] array, int start, int end, byte number) {
		
		for (int i = start; i < end; i++) {
			array[i] = number;
		}
	}
	
	public double getMaxMismatch() {
		return maxMismatch;
	}

	public void setMaxMismatch(double maxMismatch) {
		this.maxMismatch = maxMismatch;
	}

	public int getMismatch() {
		return mismatch;
	}

	public void setMismatch(int mismatch) {
		this.mismatch = mismatch;
	}
	
	public int getMaxFileSize() {
		return maxFileSize;
	}

	public void setMaxFileSize(int maxFileSize) {
		this.maxFileSize = maxFileSize;
	}

	public File getFirstFile() {
		return firstFile;
	}

	public void setFirstFile(File firstFile) {
		this.firstFile = firstFile;
	}

	public File getSecondFile() {
		return secondFile;
	}

	public void setSecondFile(File secondFile) {
		this.secondFile = secondFile;
	}

	public static void main(String[] args) throws IOException {
		
		BinaryCompare fc = new BinaryCompare();
		long start = System.currentTimeMillis();
		ArrayList<File[]> matches = fc.compareFilesInDirectory(
				new File("Z:\\"), 25, true, false);
		System.out.println("Time needed: " + (System.currentTimeMillis() - start));
		System.out.println("Matches:");
		for (File[] f : matches) {
			System.out.println(f[0].getAbsolutePath() + " *matches* " + f[1].getAbsolutePath());
		}
	}
}

Code ist optimiert, außerdem ist es jetzt auch möglich Dateien zu vergleichen, die größer als 5MB sind :lol: . Außerdem ist eine Methode implementiert um gleich ganze Ordnerstrukturen auf doppelt vorkommende Dateien zu prüfen.
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
M Dateien nach kopieren vergleichen Allgemeine Java-Themen 9
OnDemand Dateien einlesen und vergleichen Allgemeine Java-Themen 1
J XML Dateien vergleichen Allgemeine Java-Themen 9
J Dateien binär vergleichen Allgemeine Java-Themen 8
W Vergleichstool für xml-Dateien Tortoise-svn Verknüpfung Allgemeine Java-Themen 2
W ICEpdf PDF-Dateien werden mit Java 21 nicht nicht mehr vollständig dargestellt Allgemeine Java-Themen 3
Thomasneuling Java Jar datei erstellen, von Projekt, dass auch Javafx Dateien, FXML Dateien und CSS Dateien, sowie Bilder enthält? Allgemeine Java-Themen 14
G Dateien lesen Allgemeine Java-Themen 3
OnDemand Unterschiedliche jar Dateien zusammen führen Allgemeine Java-Themen 8
A Sicheres Löschen von Dateien Allgemeine Java-Themen 7
O git ignore für Intellji braucht es die .idea Dateien? Allgemeine Java-Themen 8
Master3000 Dateien zwischen verschiedenen Netzwerken senden Allgemeine Java-Themen 17
L Jar Dateien in Classpath laden ab JDK 9+ Allgemeine Java-Themen 11
d.lumpi JDA eclipse dateien versenden Allgemeine Java-Themen 4
O Produziert das Tool "jpackage" (ab JDK 14) .exe Dateien, die auf einer Zielumgebung ohne JRE lauffähig sind ?` Allgemeine Java-Themen 7
O Wie kann ich in Apache POI (Excel Dateien schreiben) Datumszellen in Excel erzeugen Allgemeine Java-Themen 6
T Meine Frage lautet wie ich 2 CSV Dateien miteinander in Java verbinde und Spalten die zueinander gehören durch den gleichen Key zusammen ausgebe? Allgemeine Java-Themen 5
L Dateien richtig auslesen Allgemeine Java-Themen 6
L Eclipse Runnable Jar mit Dateien Allgemeine Java-Themen 8
W Server-Thread schreibt nicht alle Dateien Allgemeine Java-Themen 6
MiMa Logging mit log4j2 in verschiedene Dateien? Allgemeine Java-Themen 22
I Klassen aus Jar-Dateien aus anderem Ordner laden Allgemeine Java-Themen 3
O jar und EXE Dateien, Pfade zur Laufzeit Allgemeine Java-Themen 1
W Dateien werden nicht gelöscht - warum? Allgemeine Java-Themen 12
B Dateien / Bilder von "webapp" Ordner bekommen? Allgemeine Java-Themen 1
P Erste Schritte Dateien löschen Allgemeine Java-Themen 4
H Erste Schritte Ausführbare Dateien lassen sich nicht starten Allgemeine Java-Themen 5
I Java als exe veröffentlichen inkl. kompletter Dateien Allgemeine Java-Themen 4
M Drucken von Dateien Allgemeine Java-Themen 10
J jar Dateien unter Windows 7 mit spezifischer jdk öffnen Allgemeine Java-Themen 2
I Laden von Informationen aus Dateien: Austauschbarkeit: 2 Dateien sinnvoll? Allgemeine Java-Themen 2
N Temporäre Dateien Allgemeine Java-Themen 3
Bluedaishi Druck Probleme mit PDF dateien Allgemeine Java-Themen 4
M Dateien schneller kopieren Allgemeine Java-Themen 1
Arif Input/Output Dateien im Jar-Programm speichern Allgemeine Java-Themen 12
D Collections.sort funktioniert nicht in exportierten .class Dateien Allgemeine Java-Themen 10
K Große JSON-Dateien schnell und effizient verarbeiten Allgemeine Java-Themen 16
J Programm zum Download von CSV-Dateien Allgemeine Java-Themen 4
V Eclipse .class Dateien Allgemeine Java-Themen 9
B Download von dateien Allgemeine Java-Themen 2
K Nicht alle class-Dateien im JRE? Allgemeine Java-Themen 2
MiMa Log4j in Dateien mit eigenem Namen schreiben Allgemeine Java-Themen 3
D Kopieren von Dateien aus einem Ordner in einen anderen Allgemeine Java-Themen 6
C Dateien in Jar aufrufen Allgemeine Java-Themen 14
X NetBeans Bilder und andere Dateien ins .jar schreiben und wieder aus .jar lesen Allgemeine Java-Themen 6
JavaWolf165 Externe .jar-Dateien in .jar-Datei intigrieren Allgemeine Java-Themen 0
X Dateien für Benutzer Sperren Allgemeine Java-Themen 4
D Dateien aus den Internet herunterladen Allgemeine Java-Themen 6
L Methoden Dateien älter als 30 Tage? Allgemeine Java-Themen 11
J .exe Dateien werden nicht gestartet obwohl Pfad richtig Allgemeine Java-Themen 6
RalleYTN Classpath Native Dateien(DLL, SO, JNILIB) Allgemeine Java-Themen 2
J Java .jar Dateien zusammenführen Allgemeine Java-Themen 1
L Best Practice Log Dateien analysieren und eventuell passende Daten am Chart darstellen Allgemeine Java-Themen 1
F Platzsparende Alternative zu .txt-Dateien Allgemeine Java-Themen 12
X Dateien von der Jar zum Ordner kopieren. Allgemeine Java-Themen 4
Ananaskirsche Input/Output Dateien im Ordner Allgemeine Java-Themen 8
A Input/Output Liste der Dateien in einem Ordner in einer Jar Datei erhalten Allgemeine Java-Themen 11
X Herunterladen von Dateien aus dem Internet Allgemeine Java-Themen 2
V Input/Output Sound Dateien aus Jar laden Allgemeine Java-Themen 18
M Dateien aus einem Verzeichnis auf einem Server auflisten Allgemeine Java-Themen 5
H PDFBox akzeptiert Dateien nicht Allgemeine Java-Themen 1
B Java - einlesen von Dateien und herausschneiden von XML Dokumenten Allgemeine Java-Themen 5
A Input/Output Spätes Schreiben von Dateien der JVM Allgemeine Java-Themen 3
M Zwei unterschiedliche JAR Dateien mit ANT erstellen Allgemeine Java-Themen 8
Thallius Dateien Zippen und wieder heraus lesen? Allgemeine Java-Themen 4
T Dateien zur Laufzeit in Java-Programm packen? Allgemeine Java-Themen 3
Maxim6394 Jar Dateien starten nicht Allgemeine Java-Themen 7
U Eclipse Java Programm beschädigt .tar.gz dateien beim Entpacken Allgemeine Java-Themen 7
GUI-Programmer Mp3 Dateien bearbeiten und speichern Allgemeine Java-Themen 3
S Exklusive Sperre auf Dateien: FileChannel, FileLock Allgemeine Java-Themen 0
Bluedaishi Dateien löschen die älter als das aktuelle Datum sind Allgemeine Java-Themen 9
T Ordner samt Dateien kopieren Allgemeine Java-Themen 11
R Importieren von Txt-Dateien in AbstractTableModel Allgemeine Java-Themen 0
C Dateien komprimieren und verschlüsseln Allgemeine Java-Themen 3
F Eclipse Eclipse kompiliert nicht mehr die aktuellen Dateien Allgemeine Java-Themen 2
R Java Dateien "verschlüsseln" Allgemeine Java-Themen 2
L Passwortgeschützte Dateien Allgemeine Java-Themen 6
A Datentypen Dateien umbenennen mit Dateiendungen - Dateiendungen ausgeben Allgemeine Java-Themen 2
L Reparieren beschädigter PDF Dateien Allgemeine Java-Themen 3
F Dateien ins Array lagern und Optionen zur Auswahl, Allgemeine Java-Themen 5
B Umbenennen von Dateien Allgemeine Java-Themen 2
B Erste Schritte Plugin erkennen und Class Dateien anzeigen lassen Allgemeine Java-Themen 3
W Best Practice Dateien parsen Allgemeine Java-Themen 3
B Dateien verschwinden aus bin Ordner?! Allgemeine Java-Themen 5
B Dateien prüfen auf Gleichheit Allgemeine Java-Themen 5
M Java Dateien verschieben Allgemeine Java-Themen 2
R Wav-Dateien wiederholt abspielen Allgemeine Java-Themen 2
L Methoden Verarbeitung von Größen Dateien Allgemeine Java-Themen 9
B Alt-Griechisch Zeichen in Dateien Allgemeine Java-Themen 2
M JAR Dateien nur mit Compiler Level 1.6 ausführbar Allgemeine Java-Themen 8
E Zugriff auf Dateien im Filesystem überwachen Allgemeine Java-Themen 5
G .jar Dateien lassen sich nicht mehr öffnen Allgemeine Java-Themen 2
M Datentypen Jar-Dateien öffnen nicht mit Java Allgemeine Java-Themen 4
C Mit Java PDF Dateien bearbeiten. Allgemeine Java-Themen 2
B Input/Output .java-Dateien auslesen Allgemeine Java-Themen 17
B Methoden Alle Methoden und Variablen aus Java-Dateien auslesen. Allgemeine Java-Themen 7
E Vorschläge, effizientes Hashing von Dateien für vergleich Allgemeine Java-Themen 7
W Vergleich eines Datenträgers auf neue Dateien Allgemeine Java-Themen 14
C Java-Dateien in einheitlichen Zeichensatz umwandeln Allgemeine Java-Themen 10
E Dateien aus / im JAR Allgemeine Java-Themen 2

Ähnliche Java Themen

Neue Themen


Oben