Here you can find the source of compareContents(File file1, File file2)
Parameter | Description |
---|---|
IllegalArgumentException | if file1 or file2 is Check#validFile not valid; |
SecurityException | if a security manager exists and denies read access to either file |
IOException | if an I/O problem occurs |
public static long compareContents(File file1, File file2) throws IllegalArgumentException, SecurityException, IOException
/*/*from www .j ava 2s .c om*/ Copyright ? 2008 Brent Boyer This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public License for more details. You should have received a copy of the Lesser GNU General Public License along with this program (see the license directory in this project). If not, see <http://www.gnu.org/licenses/>. */ import bb.science.FormatUtil; import bb.util.Check; import bb.util.StringUtil; import bb.util.ThrowableUtil; import bb.util.logging.LogUtil; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.util.Random; import java.util.logging.Level; import org.junit.Assert; import org.junit.Test; public class Main{ /** * Compares the contents of the two supplied normal files, byte by byte. * Returns the (zero-based) index of the first byte position where they differ, else returns -1 if they are identical. * If one file is smaller than the other, but the bytes in the 2 files are identical up to where the smaller ends, * then the value returned is the length of the smaller file (i.e. the index of the first extra byte in the larger file). * <p> * Contract: the result is -1 if and only the files are identical, else is >= 0. * <p> * @throws IllegalArgumentException if file1 or file2 is {@link Check#validFile not valid}; * @throws SecurityException if a security manager exists and denies read access to either file * @throws IOException if an I/O problem occurs */ public static long compareContents(File file1, File file2) throws IllegalArgumentException, SecurityException, IOException { Check.arg().validFile(file1); Check.arg().validFile(file2); InputStream in1 = null; InputStream in2 = null; try { in1 = new FileInputStream(file1); in2 = new FileInputStream(file2); int bufferSize = calcBufferSize(file1, file2); byte[] bytes1 = new byte[bufferSize]; byte[] bytes2 = new byte[bufferSize]; long index = 0; while (true) { // attempt a fast bulk read into byte arrays: int nRead1 = in1.read(bytes1); int nRead2 = in2.read(bytes2); // see if any ran out of data: int minRead = Math.min(nRead1, nRead2); if (minRead == -1) { // at least one ran out of data if (nRead1 == nRead2) return -1; // both ran out of data, and so the files are identical else return index; // only 1 ran out of data, and so the files are NOT identical } // compare those parts of the byte[] which are both populated with data: int offset = findWhereDiffer(bytes1, bytes2, minRead); if (offset > -1) return index + offset; // a difference was found, return the index where first one occurs else index += minRead; // no differences found so far, so increment index and continue search // NASTY CORNER CASE: one of the bulk reads failed to pull in as much data as the other; resolve by doing a slow byte by byte read and compare: if (nRead1 != nRead2) { LogUtil.getLogger2() .logp(Level.WARNING, "FileUtil", "compareContents", "nRead1 = " + nRead1 + " != nRead2 = " + nRead2 + "; while need to resolve by doing a slow byte by byte read and compare"); for (; nRead1 < nRead2; nRead1++) { int read1 = in1.read(); if ((read1 == -1) || (read1 != bytes2[nRead1])) return index; else ++index; } for (; nRead2 < nRead1; nRead2++) { int read2 = in2.read(); if ((read2 == -1) || (read2 != bytes1[nRead2])) return index; else ++index; } } } } finally { StreamUtil.close(in1); StreamUtil.close(in2); } } private static int calcBufferSize(File file1, File file2) { int lowerBound = 16; int upperBound = 1024 * 1024; long minLength = Math.min(file1.length(), file2.length()); if (minLength < lowerBound) return lowerBound; else if (minLength > upperBound) return upperBound; else return (int) minLength; } private static int findWhereDiffer(byte[] bytes1, byte[] bytes2, int limit) { for (int i = 0; i < limit; i++) { if (bytes1[i] != bytes2[i]) return i; } return -1; } }