1 package be
.nikiroo
.utils
.streams
;
3 import java
.io
.IOException
;
4 import java
.io
.InputStream
;
7 * This {@link InputStream} will change some of its content by replacing it with
12 public class ReplaceInputStream
extends BufferedInputStream
{
14 * The minimum size of the internal buffer (could be more if at least one of
15 * the 'FROM' bytes arrays is > 2048 bytes — in that case the
16 * buffer will be twice the largest size of the 'FROM' bytes arrays).
18 * This is a different buffer than the one from the inherited class.
20 static private final int MIN_BUFFER_SIZE
= 4096;
22 private byte[][] froms
;
24 private int maxFromSize
;
25 private int maxToSize
;
27 private byte[] source
;
32 * Create a {@link ReplaceInputStream} that will replace <tt>from</tt> with
36 * the under-laying {@link InputStream}
38 * the {@link String} to replace
40 * the {@link String} to replace with
42 public ReplaceInputStream(InputStream in
, String from
, String to
) {
43 this(in
, StreamUtils
.bytes(from
), StreamUtils
.bytes(to
));
47 * Create a {@link ReplaceInputStream} that will replace <tt>from</tt> with
51 * the under-laying {@link InputStream}
53 * the value to replace
55 * the value to replace with
57 public ReplaceInputStream(InputStream in
, byte[] from
, byte[] to
) {
58 this(in
, new byte[][] { from
}, new byte[][] { to
});
62 * Create a {@link ReplaceInputStream} that will replace all <tt>froms</tt>
65 * Note that they will be replaced in order, and that for each <tt>from</tt>
66 * a <tt>to</tt> must correspond.
69 * the under-laying {@link InputStream}
71 * the values to replace
73 * the values to replace with
75 public ReplaceInputStream(InputStream in
, String
[] froms
, String
[] tos
) {
76 this(in
, StreamUtils
.bytes(froms
), StreamUtils
.bytes(tos
));
80 * Create a {@link ReplaceInputStream} that will replace all <tt>froms</tt>
83 * Note that they will be replaced in order, and that for each <tt>from</tt>
84 * a <tt>to</tt> must correspond.
87 * the under-laying {@link InputStream}
89 * the values to replace
91 * the values to replace with
93 public ReplaceInputStream(InputStream in
, byte[][] froms
, byte[][] tos
) {
96 if (froms
.length
!= tos
.length
) {
97 throw new IllegalArgumentException(
98 "For replacing, each FROM must have a corresponding TO");
105 for (int i
= 0; i
< froms
.length
; i
++) {
106 maxFromSize
= Math
.max(maxFromSize
, froms
[i
].length
);
110 for (int i
= 0; i
< tos
.length
; i
++) {
111 maxToSize
= Math
.max(maxToSize
, tos
[i
].length
);
114 // We need at least maxFromSize so we can iterate and replace
115 source
= new byte[Math
.max(2 * maxFromSize
, MIN_BUFFER_SIZE
)];
121 protected int read(InputStream in
, byte[] buffer
, int off
, int len
)
123 if (len
< maxToSize
|| source
.length
< maxToSize
* 2) {
124 throw new IOException(
125 "An underlaying buffer is too small for these replace values");
128 // We need at least one byte of data to process
129 if (available() < Math
.max(maxFromSize
, 1) && !eof
) {
131 slen
= in
.read(source
);
134 // Note: very simple, not efficient implementation; sorry.
136 while (spos
< slen
&& count
< len
- maxToSize
) {
137 boolean replaced
= false;
138 for (int i
= 0; i
< froms
.length
; i
++) {
139 if (froms
[i
] != null && froms
[i
].length
> 0
140 && StreamUtils
.startsWith(froms
[i
], source
, spos
, slen
)) {
141 if (tos
[i
] != null && tos
[i
].length
> 0) {
142 System
.arraycopy(tos
[i
], 0, buffer
, off
+ spos
,
144 count
+= tos
[i
].length
;
147 spos
+= froms
[i
].length
;
154 buffer
[off
+ count
++] = source
[spos
++];