Skip to content

Commit 182d654

Browse files
kilinkbclozel
authored andcommitted
Add optimized DataBufferInputStream overrides
Add optimized DataBufferInputStream overrides for readNBytes, skip, and transferTo; all of them allocate byte buffers which we can either avoid (in the case of skip) or size more precisely since the number of remaining bytes is known. Closes gh-34799 Signed-off-by: Patrick Strawderman <pstrawderman@netflix.com>
1 parent bbae625 commit 182d654

File tree

2 files changed

+80
-1
lines changed

2 files changed

+80
-1
lines changed

spring-core/src/main/java/org/springframework/core/io/buffer/DataBufferInputStream.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import java.io.IOException;
2020
import java.io.InputStream;
21+
import java.io.OutputStream;
22+
import java.util.Objects;
2123

2224
import org.springframework.util.Assert;
2325

@@ -103,10 +105,44 @@ public void close() {
103105
this.closed = true;
104106
}
105107

108+
@Override
109+
public byte[] readNBytes(int len) throws IOException {
110+
if (len < 0) {
111+
throw new IllegalArgumentException("len < 0");
112+
}
113+
checkClosed();
114+
int size = Math.min(available(), len);
115+
byte[] out = new byte[size];
116+
this.dataBuffer.read(out);
117+
return out;
118+
}
119+
120+
@Override
121+
public long skip(long n) throws IOException {
122+
checkClosed();
123+
if (n <= 0) {
124+
return 0L;
125+
}
126+
int skipped = Math.min(available(), n > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) n);
127+
this.dataBuffer.readPosition(Math.min(this.end, this.dataBuffer.readPosition() + skipped));
128+
return skipped;
129+
}
130+
131+
@Override
132+
public long transferTo(OutputStream out) throws IOException {
133+
Objects.requireNonNull(out, "out");
134+
checkClosed();
135+
if (available() == 0) {
136+
return 0L;
137+
}
138+
byte[] buf = readAllBytes();
139+
out.write(buf);
140+
return buf.length;
141+
}
142+
106143
private void checkClosed() throws IOException {
107144
if (this.closed) {
108145
throw new IOException("DataBufferInputStream is closed");
109146
}
110147
}
111-
112148
}

spring-core/src/test/java/org/springframework/core/io/buffer/DataBufferTests.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.core.io.buffer;
1818

19+
import java.io.ByteArrayOutputStream;
1920
import java.io.InputStream;
2021
import java.io.OutputStream;
2122
import java.nio.ByteBuffer;
@@ -342,6 +343,48 @@ void inputStream(DataBufferFactory bufferFactory) throws Exception {
342343
assertThat(len).isEqualTo(3);
343344
assertThat(bytes).containsExactly('c', 'd', 'e');
344345

346+
buffer.readPosition(0);
347+
inputStream = buffer.asInputStream();
348+
assertThat(inputStream.readAllBytes()).asString().isEqualTo("abcde");
349+
assertThat(inputStream.available()).isEqualTo(0);
350+
assertThat(inputStream.readAllBytes()).isEmpty();
351+
352+
buffer.readPosition(0);
353+
inputStream = buffer.asInputStream();
354+
inputStream.mark(5);
355+
assertThat(inputStream.readNBytes(0)).isEmpty();
356+
assertThat(inputStream.readNBytes(1000)).asString().isEqualTo("abcde");
357+
inputStream.reset();
358+
assertThat(inputStream.readNBytes(3)).asString().isEqualTo("abc");
359+
assertThat(inputStream.readNBytes(2)).asString().isEqualTo("de");
360+
assertThat(inputStream.readNBytes(10)).isEmpty();
361+
362+
buffer.readPosition(0);
363+
inputStream = buffer.asInputStream();
364+
inputStream.mark(5);
365+
assertThat(inputStream.skip(1)).isEqualTo(1);
366+
assertThat(inputStream.readAllBytes()).asString().isEqualTo("bcde");
367+
assertThat(inputStream.skip(10)).isEqualTo(0);
368+
assertThat(inputStream.available()).isEqualTo(0);
369+
inputStream.reset();
370+
assertThat(inputStream.skip(100)).isEqualTo(5);
371+
assertThat(inputStream.available()).isEqualTo(0);
372+
373+
buffer.readPosition(0);
374+
inputStream = buffer.asInputStream();
375+
inputStream.mark(5);
376+
ByteArrayOutputStream out = new ByteArrayOutputStream();
377+
assertThat(inputStream.transferTo(out)).isEqualTo(5);
378+
assertThat(out.toByteArray()).asString().isEqualTo("abcde");
379+
assertThat(inputStream.available()).isEqualTo(0);
380+
out.reset();
381+
inputStream.reset();
382+
assertThat(inputStream.read()).isEqualTo('a');
383+
assertThat(inputStream.transferTo(out)).isEqualTo(4);
384+
assertThat(out.toByteArray()).asString().isEqualTo("bcde");
385+
assertThat(inputStream.available()).isEqualTo(0);
386+
assertThat(inputStream.transferTo(OutputStream.nullOutputStream())).isEqualTo(0);
387+
345388
release(buffer);
346389
}
347390

0 commit comments

Comments
 (0)