< prev index next >

src/java.base/share/classes/java/nio/file/Files.java

Print this page

        

@@ -89,10 +89,13 @@
  *
  * @since 1.7
  */
 
 public final class Files {
+    // buffer size used for reading and writing
+    private static final int BUFFER_SIZE = 8192;
+
     private Files() { }
 
     /**
      * Returns the {@code FileSystemProvider} to delegate to.
      */

@@ -1529,10 +1532,94 @@
     public static boolean isSameFile(Path path, Path path2) throws IOException {
         return provider(path).isSameFile(path, path2);
     }
 
     /**
+     * Finds and returns the position of the first mismatched byte in the content
+     * of two files, or {@code -1L} if there is no mismatch. The position will be
+     * in the inclusive range of {@code 0L} up to the size (in bytes) of the
+     * smaller file.
+     *
+     * <p> Two files are considered to match if they satisfy one of the following
+     * conditions:
+     * <ul>
+     * <li> The two paths locate the {@link #isSameFile(Path, Path) same file},
+     *      even if two {@link Path#equals(Object) equal} paths locate a file
+     *      does not exist, or </li>
+     * <li> The two files are the same size, and every byte in the first file
+     *      is identical to the corresponding byte in the second file. </li>
+     * </ul>
+     *
+     * <p> Otherwise there is a mismatch between the two files and the value
+     * returned by this method is:
+     * <ul>
+     * <li> The position of the first mismatched byte, or </li>
+     * <li> The size of the smaller file (in bytes) when the files are different
+     *      sizes and every byte of the smaller file is identical to the
+     *      corresponding byte of the larger file. </li>
+     * </ul>
+     *
+     * <p> This method may not be atomic with respect to other file system
+     * operations. If the file system and files remain static then this method
+     * is <i>reflexive</i> (for {@code Path} {@code f}, {@code mismatch(f,f)}
+     * returns {@code -1L}), and <i>symmetric</i> (for two {@code Paths} {@code
+     * f} and {@code g}, {@code mismatch(f,g)} will return the same value as
+     * {@code mismatch(g,f)}).
+     *
+     * @param   path
+     *          the path to the first file
+     * @param   path2
+     *          the path to the second file
+     *
+     * @return  the position of the first mismatch or {@code -1L} if no mismatch
+     *
+     * @throws  IOException
+     *          if an I/O error occurs
+     * @throws  SecurityException
+     *          In the case of the default provider, and a security manager is
+     *          installed, the {@link SecurityManager#checkRead(String) checkRead}
+     *          method is invoked to check read access to both files.
+     *
+     * @since 12
+     */
+    public static long mismatch(Path path, Path path2) throws IOException {
+        if (isSameFile(path, path2)) {
+            return -1;
+        }
+        byte[] buffer1 = new byte[Files.BUFFER_SIZE];
+        byte[] buffer2 = new byte[Files.BUFFER_SIZE];
+        try (InputStream in1 = Files.newInputStream(path);
+             InputStream in2 = Files.newInputStream(path2);) {
+            int totalRead = 0;
+            while (true) {
+                int nRead1 = in1.readNBytes(buffer1, 0, Files.BUFFER_SIZE);
+                int nRead2 = in2.readNBytes(buffer2, 0, Files.BUFFER_SIZE);
+                if (nRead1 == 0 && nRead2 == 0) {
+                    // both files reached EOF
+                    return -1;
+                } else if (nRead1 == 0 || nRead2 == 0) {
+                    // one but not both files reached EOF
+                    return totalRead;
+                } else if (nRead1 != nRead2) {
+                    // there's always a mismatch when nRead1 != nRead2
+                    return totalRead + Arrays.mismatch(buffer1, 0, nRead1, buffer2, 0, nRead2);
+                } else {
+                    int i = Arrays.mismatch(buffer1, 0, nRead1, buffer2, 0, nRead1);
+                    if (i > -1) {
+                        return totalRead + i;
+                    }
+                    if (nRead1 < Files.BUFFER_SIZE) {
+                        // we've reached the end of the files, but found no mismatch
+                        return -1;
+                    }
+                    totalRead += nRead1;
+                }
+            }
+        }
+    }
+
+    /**
      * Tells whether or not a file is considered <em>hidden</em>. The exact
      * definition of hidden is platform or provider dependent. On UNIX for
      * example a file is considered to be hidden if its name begins with a
      * period character ('.'). On Windows a file is considered hidden if it
      * isn't a directory and the DOS {@link DosFileAttributes#isHidden hidden}

@@ -2800,12 +2887,10 @@
     }
 
 
     // -- Utility methods for simple usages --
 
-    // buffer size used for reading and writing
-    private static final int BUFFER_SIZE = 8192;
 
     /**
      * Opens a file for reading, returning a {@code BufferedReader} that may be
      * used to read text from the file in an efficient manner. Bytes from the
      * file are decoded into characters using the specified charset. Reading
< prev index next >