# Dateien vergleichen



## The_S (30. Jan 2007)

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")


```
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!


----------



## Guest (30. Jan 2007)

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 (30. Jan 2007)

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 (30. Jan 2007)

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 (30. Jan 2007)

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 (30. Jan 2007)

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 (30. Jan 2007)

@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 (30. Jan 2007)

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 (30. Jan 2007)

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 (30. Jan 2007)

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 (30. Jan 2007)

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 (31. Jan 2007)

Aktualisierte Version des Quellcodes. Für Kritik und Anregugnen bin ich immernoch dankbar 


```
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 (2. Feb 2007)

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


```
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.


----------

