This is an automated email from the ASF dual-hosted git repository.

pkarwasz pushed a commit to branch feat/use-scratch-bytes
in repository https://gitbox.apache.org/repos/asf/commons-io.git

commit 73155fde9e0f1217f067a9efad9287a6f9c14423
Author: Piotr P. Karwasz <[email protected]>
AuthorDate: Sun Oct 19 10:36:20 2025 +0200

    Extend scratch buffer usage in `IOUtils`
    
    This PR applies scratch buffer reuse to three additional methods (and their 
dependents) for more consistent memory behavior. It improves memory usage and 
ensures that `consume(inputStream)` can safely replace `skip(inputStream, 
Long.MAX_VALUE)` without unnecessary allocations.
---
 src/changes/changes.xml                          |  1 +
 src/main/java/org/apache/commons/io/IOUtils.java | 26 +++++++++++++++---------
 2 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 3aa419401..680868304 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -72,6 +72,7 @@ The <action> type attribute can be add,update,fix,remove.
       <action dev="pkarwasz" type="add"                due-to="Piotr P. 
Karwasz">Add NIO channel support to `AbstractStreamBuilder`.</action>
       <action dev="pkarwasz" type="add"                due-to="Piotr P. 
Karwasz">Add CloseShieldChannel to close-shielded NIO Channels #786.</action>
       <action dev="pkarwasz" type="add"                due-to="Piotr P. 
Karwasz">Added IOUtils.checkFromIndexSize as a Java 8 backport of 
Objects.checkFromIndexSize #790.</action>
+      <action dev="pkarwasz" type="add"                due-to="Piotr P. 
Karwasz">Use scratch buffers in more IOUtils methods.</action>
       <!-- UPDATE -->
       <action type="update" dev="ggregory"             due-to="Gary Gregory, 
Dependabot">Bump org.apache.commons:commons-parent from 85 to 89 #774, 
#783.</action>
       <action type="update" dev="ggregory"             due-to="Gary 
Gregory">[test] Bump commons-codec:commons-codec from 1.18.0 to 1.19.0.</action>
diff --git a/src/main/java/org/apache/commons/io/IOUtils.java 
b/src/main/java/org/apache/commons/io/IOUtils.java
index 5d3d7cc58..6071530c0 100644
--- a/src/main/java/org/apache/commons/io/IOUtils.java
+++ b/src/main/java/org/apache/commons/io/IOUtils.java
@@ -1499,7 +1499,9 @@ public static QueueInputStream copy(final 
java.io.ByteArrayOutputStream outputSt
      * @since 2.7
      */
     public static long copy(final Reader reader, final Appendable output) 
throws IOException {
-        return copy(reader, output, CharBuffer.allocate(DEFAULT_BUFFER_SIZE));
+        try (ScratchChars scratch = IOUtils.ScratchChars.get()) {
+            return copy(reader, output, CharBuffer.wrap(scratch.array()));
+        }
     }
 
     /**
@@ -1702,7 +1704,9 @@ public static long copy(final URL url, final OutputStream 
outputStream) throws I
      */
     public static long copyLarge(final InputStream inputStream, final 
OutputStream outputStream)
             throws IOException {
-        return copy(inputStream, outputStream, DEFAULT_BUFFER_SIZE);
+        try (ScratchBytes scratch = ScratchBytes.get()) {
+            return copyLarge(inputStream, outputStream, scratch.array());
+        }
     }
 
     /**
@@ -2651,16 +2655,18 @@ public static long skip(final ReadableByteChannel 
input, final long toSkip) thro
         if (toSkip < 0) {
             throw new IllegalArgumentException("Skip count must be 
non-negative, actual: " + toSkip);
         }
-        final ByteBuffer skipByteBuffer = ByteBuffer.allocate((int) 
Math.min(toSkip, DEFAULT_BUFFER_SIZE));
         long remain = toSkip;
-        while (remain > 0) {
-            skipByteBuffer.position(0);
-            skipByteBuffer.limit((int) Math.min(remain, DEFAULT_BUFFER_SIZE));
-            final int n = input.read(skipByteBuffer);
-            if (n == EOF) {
-                break;
+        try (ScratchBytes scratch = ScratchBytes.get()) {
+            final ByteBuffer skipByteBuffer = ByteBuffer.wrap(scratch.array());
+            while (remain > 0) {
+                skipByteBuffer.position(0);
+                skipByteBuffer.limit((int) Math.min(remain, 
DEFAULT_BUFFER_SIZE));
+                final int n = input.read(skipByteBuffer);
+                if (n == EOF) {
+                    break;
+                }
+                remain -= n;
             }
-            remain -= n;
         }
         return toSkip - remain;
     }

Reply via email to