You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by GitBox <gi...@apache.org> on 2020/01/27 14:15:45 UTC

[GitHub] [commons-io] garydgregory commented on a change in pull request #101: IO-649 - Improve the performance of the contentEquals() methods.

garydgregory commented on a change in pull request #101: IO-649 - Improve the performance of the contentEquals() methods.
URL: https://github.com/apache/commons-io/pull/101#discussion_r370778414
 
 

 ##########
 File path: src/main/java/org/apache/commons/io/IOUtils.java
 ##########
 @@ -691,80 +692,173 @@ public static void closeQuietly(final Writer output) {
     }
 
     /**
-     * Compares the contents of two Streams to determine if they are equal or
-     * not.
+     * Compares the contents of two Streams to determine if they are equal or not.
      * <p>
-     * This method buffers the input internally using
-     * <code>BufferedInputStream</code> if they are not already buffered.
-     * </p>
+     * This method buffers the input internally using {@link #DEFAULT_BUFFER_SIZE} sized buffers.
      *
      * @param input1 the first stream
      * @param input2 the second stream
      * @return true if the content of the streams are equal or they both don't
      * exist, false otherwise
-     * @throws NullPointerException if either input is null
      * @throws IOException          if an I/O error occurs
      */
     @SuppressWarnings("resource")
     public static boolean contentEquals(final InputStream input1, final InputStream input2)
             throws IOException {
+        return contentEquals(input1, input2, DEFAULT_BUFFER_SIZE);
+    }
+
+    /**
+     * Compares the contents of two Streams to determine if they are equal or not.
+     * <p>
+     * This method buffers the input internally.
+     *
+     * @param input1 the first stream
+     * @param input2 the second stream
+     * @param bufferSize the size of the internal buffer to use.
+     * @return true if the content of the streams are equal or they both don't
+     * exist, false otherwise
+     * @throws IllegalArgumentException if bufferSize is less than or equal to zero.
+     * @throws IOException              if an I/O error occurs
+     * @since 2.6
+     */
+    @SuppressWarnings("resource")
+    public static boolean contentEquals(final InputStream input1, final InputStream input2, final int bufferSize)
+            throws IOException {
+        if (bufferSize <= 0) {
+            throw new IllegalArgumentException("Buffer size must be positive: " + bufferSize);
+        }
+
         if (input1 == input2) {
             return true;
         }
         if (input1 == null ^ input2 == null) {
             return false;
         }
-        final BufferedInputStream bufferedInput1 = buffer(input1);
-        final BufferedInputStream bufferedInput2 = buffer(input2);
-        int ch = bufferedInput1.read();
-        while (EOF != ch) {
-            final int ch2 = bufferedInput2.read();
-            if (ch != ch2) {
+
+        int input1NumBytesRead = 0;
+        int input2NumBytesRead = 0;
+        final byte[] input1Buffer = new byte[bufferSize];
+        final byte[] input2Buffer = new byte[bufferSize];
+        do {
+            input1NumBytesRead = fillBuffer(input1, input1Buffer);
+            input2NumBytesRead = fillBuffer(input2, input2Buffer);
+
+            if (input2NumBytesRead != input1NumBytesRead || !Arrays.equals(input1Buffer, input2Buffer)) {
                 return false;
             }
-            ch = bufferedInput1.read();
-        }
-        return bufferedInput2.read() == EOF;
+        } while (input1NumBytesRead == bufferSize && input2NumBytesRead == bufferSize);
+
+        return input1.read() == EOF && input2.read() == EOF;
     }
 
+
     /**
-     * Compares the contents of two Readers to determine if they are equal or
-     * not.
+     * This method fills the provided byte array buffer from the provided <code>InputStream</code>.  When this method
+     * returns the buffer will either be full or the InputStream will be fully consumed.
+     *
+     * @param inputStream the InputStream from which to read
+     * @param buffer the buffer to fill
+     * @return the number of bytes placed in the buffer.  If this is equal to <code>buffer.length</code> then the
+     * buffer was completely filled.  If it is less than <code>buffer.length</code>, then the InputStream has been
+     * fully consumed.
+     * @throws IOException if an I/O error occurs.
+     */
+    private static int fillBuffer(final InputStream inputStream, final byte[] buffer) throws IOException {
+        int totalBytesRead = 0;
+        int bytesRead = 0;
+        do {
+            totalBytesRead += bytesRead;
+            bytesRead = inputStream.read(buffer, totalBytesRead, buffer.length - totalBytesRead);
+        } while (bytesRead != -1 && totalBytesRead < buffer.length);
 
 Review comment:
   Avoid using magic numbers; we have a constant called EOF for this purpose.
   

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services