src/main/java/net/kolotyluk/java/files/Files.java
public static Boolean contentEquals(Path file1, Path file2) throws IOException
  {
      if (!java.nio.file.Files.isRegularFile(file1))
	      throw new IllegalArgumentException(file1 + "is not a regular file");

	  if (!java.nio.file.Files.isRegularFile(file2))
		  throw new IllegalArgumentException(file2 + "is not a regular file");
    
	  FileChannel channel1 = null;
	  FileChannel channel2 = null;
    
	  MappedByteBuffer buffer1 = null;
	  MappedByteBuffer buffer2 = null;
    
	  try
	  {
		  long size1 = java.nio.file.Files.size(file1);
		  long size2 = java.nio.file.Files.size(file2);
        
		  if (size1 != size2) return false;
        
		  long position = 0;
		  long length = Math.min(Integer.MAX_VALUE, size1 - position);

		  channel1 = FileChannel.open(file1);
		  channel2 = FileChannel.open(file2);

		  // Cannot map files larger than Integer.MAX_VALUE,
		  // so we have to do it in pieces.

		  while (length > 0)
		  {
			  buffer1 = channel1.map(MapMode.READ_ONLY, position, length);
			  buffer2 = channel2.map(MapMode.READ_ONLY, position, length);
			  // if (!buffer1.equals(buffer2)) return false;
			  // The line above is much slower than the line below.
			  // It should not be, but it is, possibly because it is
			  // loading the entire buffer into memory before comparing
			  // the contents. See the corresponding unit test. EK
			  for (int i = 0; i < length; i++) if (buffer1.get() != buffer2.get()) return false;
			  position += length;
			  length = Math.min(Integer.MAX_VALUE, size1 - position);
			  cleanDirectByteBuffer(buffer1); buffer1 = null;
			  cleanDirectByteBuffer(buffer2); buffer2 = null;
		  }
	  }
	  finally
	  {
		  // Is is important to clean up so we do not hold any
		  // file locks, in case the caller wants to do something
		  // else with the files.
		  
		  // In terms of functional programming, holding a lock after
		  // returning to the caller would be an unwelcome side-effect.

		  cleanDirectByteBuffer(buffer1);
		  cleanDirectByteBuffer(buffer2);
    	
		  if (channel1 != null) try
		  {
			  channel1.close();
		  }
		  catch (IOException e)
		  {
			  if (channel2 != null) channel2.close();
			  throw e;
		  }

		  if (channel2 != null) channel2.close();
	  }
    
	  return true;
  }
public static Boolean contentEquals(Path file1, Path file2) throws IOException
  {
      if (!java.nio.file.Files.isRegularFile(file1))
	      throw new IllegalArgumentException(file1 + "is not a regular file");

	  if (!java.nio.file.Files.isRegularFile(file2))
		  throw new IllegalArgumentException(file2 + "is not a regular file");
    
	  FileChannel channel1 = null;
	  FileChannel channel2 = null;
    
	  MappedByteBuffer buffer1 = null;
	  MappedByteBuffer buffer2 = null;
    
	  try
	  {
		  long size1 = java.nio.file.Files.size(file1);
		  long size2 = java.nio.file.Files.size(file2);
        
		  if (size1 != size2) return false;
        
		  long position = 0;
		  long length = Math.min(Integer.MAX_VALUE, size1 - position);

		  channel1 = FileChannel.open(file1);
		  channel2 = FileChannel.open(file2);

		  // Cannot map files larger than Integer.MAX_VALUE,
		  // so we have to do it in pieces.

		  while (length > 0)
		  {
			  buffer1 = channel1.map(MapMode.READ_ONLY, position, length);
			  buffer2 = channel2.map(MapMode.READ_ONLY, position, length);
			  // if (!buffer1.equals(buffer2)) return false;
			  // The line above is much slower than the line below.
			  // It should not be, but it is, possibly because it is
			  // loading the entire buffer into memory before comparing
			  // the contents. See the corresponding unit test. EK
			  for (int i = 0; i < length; i++) if (buffer1.get() != buffer2.get()) return false;
			  position += length;
			  length = Math.min(Integer.MAX_VALUE, size1 - position);
			  cleanDirectByteBuffer(buffer1); buffer1 = null;
			  cleanDirectByteBuffer(buffer2); buffer2 = null;
		  }
	  }
	  finally
	  {
		  // Is is important to clean up so we do not hold any
		  // file locks, in case the caller wants to do something
		  // else with the files.
		  
		  // In terms of functional programming, holding a lock after
		  // returning to the caller would be an unwelcome side-effect.

		  cleanDirectByteBuffer(buffer1);
		  cleanDirectByteBuffer(buffer2);
    	
		  if (channel1 != null) try
		  {
			  channel1.close();
		  }
		  catch (IOException e)
		  {
			  if (channel2 != null) channel2.close();
			  throw e;
		  }

		  if (channel2 != null) channel2.close();
	  }
    
	  return true;
  }
Identical File Contents

<p>Uses
<a href="http://en.wikipedia.org/wiki/Memory-mapped_file">Memory Mapped Files</a>
for fast comparison of large files. This is about 4 times faster than calling</p><pre>
<a href="http://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/FileUtils.html#contentEquals%28java.io.File,%20java.io.File%29">org.apache.commons.io.FileUtils.contentEquals(File file1,File file2)</a></pre>
<p>with identical 4
<a href="http://en.wikipedia.org/wiki/Gibibyte">GiB</a>
files. Performance may suffer slightly for smaller files.
A future version may be optimized for smaller files too.</p>

<p>Useful for checking if media files, such as music and video,
have identical or duplicate content. Video files can easily
be over 4 GiB in size. Technically this method will compare
files as large as the file system supports.</p>

<p>Performance is about 16 seconds for two 4 GiB files with
identical content on an Intel Xeon 5580 at 3.2 GHz using a
file system on a LSI MegaRAID SAS 9266-8i.</p>

@param file1 1st file to be compared
@param file2 2nd file to be compared
@return true when both files have identical contents
@throws IllegalArgumentException if the arguments are not files.
@throws IOException if there is a problem with File I/O
@throws RuntimeException if there was a problem unmapping the
buffers or closing the channels, which may leave one or more
files locked for read.