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

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 1cfb7ce10ed3 CAMEL-26390: camel-core - IOConverter: convert an 
InputStream to String without the BufferedReader/StringBuilder chain (#28649)
1cfb7ce10ed3 is described below

commit 1cfb7ce10ed3d0b83dbe4d311428c43bbe596c48
Author: Adriano Machado <[email protected]>
AuthorDate: Thu Oct 29 01:38:49 2026 -0400

    CAMEL-26390: camel-core - IOConverter: convert an InputStream to String 
without the BufferedReader/StringBuilder chain (#28649)
    
    Co-authored-by: Claude Opus 5.5 <[email protected]>
---
 .../org/apache/camel/converter/IOConverter.java    |  8 +++-
 .../apache/camel/converter/IOConverterTest.java    | 47 ++++++++++++++++++++++
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git 
a/core/camel-base/src/main/java/org/apache/camel/converter/IOConverter.java 
b/core/camel-base/src/main/java/org/apache/camel/converter/IOConverter.java
index 9c924c2e2b3e..e4b816c0efa5 100644
--- a/core/camel-base/src/main/java/org/apache/camel/converter/IOConverter.java
+++ b/core/camel-base/src/main/java/org/apache/camel/converter/IOConverter.java
@@ -234,7 +234,13 @@ public final class IOConverter {
 
     @Converter(order = 31)
     public static String toString(InputStream in, Exchange exchange) throws 
IOException {
-        return toString(toReader(in, exchange));
+        Charset charset = ExchangeHelper.getCharset(exchange);
+        try {
+            // decode all the bytes at once, which avoids the buffers of a 
reader and a string builder
+            return new String(in.readAllBytes(), charset);
+        } finally {
+            IOHelper.close(in, "input stream", LOG);
+        }
     }
 
     @Converter(order = 32)
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/converter/IOConverterTest.java 
b/core/camel-core/src/test/java/org/apache/camel/converter/IOConverterTest.java
index 41ac8a9ce52e..57acf851eaf8 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/converter/IOConverterTest.java
+++ 
b/core/camel-core/src/test/java/org/apache/camel/converter/IOConverterTest.java
@@ -23,6 +23,7 @@ import java.io.BufferedWriter;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.Reader;
@@ -287,4 +288,50 @@ public class IOConverterTest extends ContextTestSupport {
         assertEquals("UTF-8", c.name());
     }
 
+    @Test
+    public void testToStringInputStreamDecodesWithExchangeCharsetAndCloses() 
throws Exception {
+        // multi byte characters at every offset, and longer than the buffers 
of a reader
+        String text = "Grüße aus 東京 ".repeat(2000);
+        for (Charset charset : new Charset[] { StandardCharsets.UTF_8, 
StandardCharsets.UTF_16 }) {
+            Exchange exchange = new DefaultExchange(context);
+            exchange.setProperty(Exchange.CHARSET_NAME, charset.name());
+            CloseTrackingInputStream is = new 
CloseTrackingInputStream(text.getBytes(charset));
+
+            assertEquals(text, IOConverter.toString(is, exchange), 
charset.name());
+            assertTrue(is.closed, "the stream is closed after reading it");
+        }
+    }
+
+    @Test
+    public void testToStringInputStreamReplacesMalformedInput() throws 
Exception {
+        Exchange exchange = new DefaultExchange(context);
+        exchange.setProperty(Exchange.CHARSET_NAME, "UTF-8");
+        InputStream is = new ByteArrayInputStream(new byte[] { 'a', (byte) 
0xC3, 'b' });
+
+        assertEquals("a�b", IOConverter.toString(is, exchange));
+    }
+
+    @Test
+    public void testToStringInputStreamReadsFromCurrentPosition() throws 
Exception {
+        InputStream is = new ByteArrayInputStream("Hello 
World".getBytes(StandardCharsets.UTF_8));
+        assertEquals(6, is.skip(6));
+
+        assertEquals("World", IOConverter.toString(is, null));
+    }
+
+    private static final class CloseTrackingInputStream extends 
ByteArrayInputStream {
+
+        private boolean closed;
+
+        CloseTrackingInputStream(byte[] data) {
+            super(data);
+        }
+
+        @Override
+        public void close() throws IOException {
+            closed = true;
+            super.close();
+        }
+    }
+
 }

Reply via email to