Skip to content

Commit 9ac451e

Browse files
committed
Refactor Base64 I/O streams
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/codec/trunk@1064424 13f79535-47bb-0310-9956-ffa450edef68
1 parent 07b5e30 commit 9ac451e

2 files changed

Lines changed: 7 additions & 218 deletions

File tree

src/java/org/apache/commons/codec/binary/Base64InputStream.java

Lines changed: 3 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717

1818
package org.apache.commons.codec.binary;
1919

20-
import java.io.FilterInputStream;
21-
import java.io.IOException;
2220
import java.io.InputStream;
2321

2422
/**
@@ -43,13 +41,7 @@
4341
* @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
4442
* @since 1.4
4543
*/
46-
public class Base64InputStream extends FilterInputStream {
47-
48-
private final boolean doEncode;
49-
50-
private final Base64 base64;
51-
52-
private final byte[] singleByte = new byte[1];
44+
public class Base64InputStream extends BaseNCodecInputStream {
5345

5446
/**
5547
* Creates a Base64InputStream such that all data read is Base64-decoded from the original provided InputStream.
@@ -71,9 +63,7 @@ public Base64InputStream(InputStream in) {
7163
* true if we should encode all data read from us, false if we should decode.
7264
*/
7365
public Base64InputStream(InputStream in, boolean doEncode) {
74-
super(in);
75-
this.doEncode = doEncode;
76-
this.base64 = new Base64(false);
66+
super(in, new Base64(false), doEncode);
7767
}
7868

7969
/**
@@ -93,97 +83,6 @@ public Base64InputStream(InputStream in, boolean doEncode) {
9383
* If lineLength <= 0, the lineSeparator is not used. If doEncode is false lineSeparator is ignored.
9484
*/
9585
public Base64InputStream(InputStream in, boolean doEncode, int lineLength, byte[] lineSeparator) {
96-
super(in);
97-
this.doEncode = doEncode;
98-
this.base64 = new Base64(lineLength, lineSeparator);
99-
}
100-
101-
/**
102-
* Reads one <code>byte</code> from this input stream.
103-
*
104-
* @return the byte as an integer in the range 0 to 255. Returns -1 if EOF has been reached.
105-
* @throws IOException
106-
* if an I/O error occurs.
107-
*/
108-
public int read() throws IOException {
109-
int r = read(singleByte, 0, 1);
110-
while (r == 0) {
111-
r = read(singleByte, 0, 1);
112-
}
113-
if (r > 0) {
114-
return singleByte[0] < 0 ? 256 + singleByte[0] : singleByte[0];
115-
}
116-
return -1;
117-
}
118-
119-
/**
120-
* Attempts to read <code>len</code> bytes into the specified <code>b</code> array starting at <code>offset</code>
121-
* from this InputStream.
122-
*
123-
* @param b
124-
* destination byte array
125-
* @param offset
126-
* where to start writing the bytes
127-
* @param len
128-
* maximum number of bytes to read
129-
*
130-
* @return number of bytes read
131-
* @throws IOException
132-
* if an I/O error occurs.
133-
* @throws NullPointerException
134-
* if the byte array parameter is null
135-
* @throws IndexOutOfBoundsException
136-
* if offset, len or buffer size are invalid
137-
*/
138-
public int read(byte b[], int offset, int len) throws IOException {
139-
if (b == null) {
140-
throw new NullPointerException();
141-
} else if (offset < 0 || len < 0) {
142-
throw new IndexOutOfBoundsException();
143-
} else if (offset > b.length || offset + len > b.length) {
144-
throw new IndexOutOfBoundsException();
145-
} else if (len == 0) {
146-
return 0;
147-
} else {
148-
int readLen = 0;
149-
/*
150-
Rationale for while-loop on (readLen == 0):
151-
-----
152-
Base64.readResults() usually returns > 0 or EOF (-1). In the
153-
rare case where it returns 0, we just keep trying.
154-
155-
This is essentially an undocumented contract for InputStream
156-
implementors that want their code to work properly with
157-
java.io.InputStreamReader, since the latter hates it when
158-
InputStream.read(byte[]) returns a zero. Unfortunately our
159-
readResults() call must return 0 if a large amount of the data
160-
being decoded was non-base64, so this while-loop enables proper
161-
interop with InputStreamReader for that scenario.
162-
-----
163-
This is a fix for CODEC-101
164-
*/
165-
while (readLen == 0) {
166-
if (!base64.hasData()) {
167-
byte[] buf = new byte[doEncode ? 4096 : 8192];
168-
int c = in.read(buf);
169-
if (doEncode) {
170-
base64.encode(buf, 0, c);
171-
} else {
172-
base64.decode(buf, 0, c);
173-
}
174-
}
175-
readLen = base64.readResults(b, offset, len);
176-
}
177-
return readLen;
178-
}
179-
}
180-
181-
/**
182-
* {@inheritDoc}
183-
*
184-
* @return false
185-
*/
186-
public boolean markSupported() {
187-
return false; // not an easy job to support marks
86+
super(in, new Base64(lineLength, lineSeparator), doEncode);
18887
}
18988
}

src/java/org/apache/commons/codec/binary/Base64OutputStream.java

Lines changed: 4 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717

1818
package org.apache.commons.codec.binary;
1919

20-
import java.io.FilterOutputStream;
21-
import java.io.IOException;
2220
import java.io.OutputStream;
2321

2422
/**
@@ -43,12 +41,7 @@
4341
* @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
4442
* @since 1.4
4543
*/
46-
public class Base64OutputStream extends FilterOutputStream {
47-
private final boolean doEncode;
48-
49-
private final Base64 base64;
50-
51-
private final byte[] singleByte = new byte[1];
44+
public class Base64OutputStream extends BaseNCodecOutputStream {
5245

5346
/**
5447
* Creates a Base64OutputStream such that all data written is Base64-encoded to the original provided OutputStream.
@@ -70,9 +63,7 @@ public Base64OutputStream(OutputStream out) {
7063
* true if we should encode all data written to us, false if we should decode.
7164
*/
7265
public Base64OutputStream(OutputStream out, boolean doEncode) {
73-
super(out);
74-
this.doEncode = doEncode;
75-
this.base64 = new Base64(false);
66+
super(out,new Base64(false), doEncode);
7667
}
7768

7869
/**
@@ -92,107 +83,6 @@ public Base64OutputStream(OutputStream out, boolean doEncode) {
9283
* If lineLength <= 0, the lineSeparator is not used. If doEncode is false lineSeparator is ignored.
9384
*/
9485
public Base64OutputStream(OutputStream out, boolean doEncode, int lineLength, byte[] lineSeparator) {
95-
super(out);
96-
this.doEncode = doEncode;
97-
this.base64 = new Base64(lineLength, lineSeparator);
98-
}
99-
100-
/**
101-
* Writes the specified <code>byte</code> to this output stream.
102-
*
103-
* @param i
104-
* source byte
105-
* @throws IOException
106-
* if an I/O error occurs.
107-
*/
108-
public void write(int i) throws IOException {
109-
singleByte[0] = (byte) i;
110-
write(singleByte, 0, 1);
86+
super(out, new Base64(lineLength, lineSeparator), doEncode);
11187
}
112-
113-
/**
114-
* Writes <code>len</code> bytes from the specified <code>b</code> array starting at <code>offset</code> to this
115-
* output stream.
116-
*
117-
* @param b
118-
* source byte array
119-
* @param offset
120-
* where to start reading the bytes
121-
* @param len
122-
* maximum number of bytes to write
123-
*
124-
* @throws IOException
125-
* if an I/O error occurs.
126-
* @throws NullPointerException
127-
* if the byte array parameter is null
128-
* @throws IndexOutOfBoundsException
129-
* if offset, len or buffer size are invalid
130-
*/
131-
public void write(byte b[], int offset, int len) throws IOException {
132-
if (b == null) {
133-
throw new NullPointerException();
134-
} else if (offset < 0 || len < 0) {
135-
throw new IndexOutOfBoundsException();
136-
} else if (offset > b.length || offset + len > b.length) {
137-
throw new IndexOutOfBoundsException();
138-
} else if (len > 0) {
139-
if (doEncode) {
140-
base64.encode(b, offset, len);
141-
} else {
142-
base64.decode(b, offset, len);
143-
}
144-
flush(false);
145-
}
146-
}
147-
148-
/**
149-
* Flushes this output stream and forces any buffered output bytes to be written out to the stream. If propogate is
150-
* true, the wrapped stream will also be flushed.
151-
*
152-
* @param propogate
153-
* boolean flag to indicate whether the wrapped OutputStream should also be flushed.
154-
* @throws IOException
155-
* if an I/O error occurs.
156-
*/
157-
private void flush(boolean propogate) throws IOException {
158-
int avail = base64.available();
159-
if (avail > 0) {
160-
byte[] buf = new byte[avail];
161-
int c = base64.readResults(buf, 0, avail);
162-
if (c > 0) {
163-
out.write(buf, 0, c);
164-
}
165-
}
166-
if (propogate) {
167-
out.flush();
168-
}
169-
}
170-
171-
/**
172-
* Flushes this output stream and forces any buffered output bytes to be written out to the stream.
173-
*
174-
* @throws IOException
175-
* if an I/O error occurs.
176-
*/
177-
public void flush() throws IOException {
178-
flush(true);
179-
}
180-
181-
/**
182-
* Closes this output stream and releases any system resources associated with the stream.
183-
*
184-
* @throws IOException
185-
* if an I/O error occurs.
186-
*/
187-
public void close() throws IOException {
188-
// Notify encoder of EOF (-1).
189-
if (doEncode) {
190-
base64.encode(singleByte, 0, -1);
191-
} else {
192-
base64.decode(singleByte, 0, -1);
193-
}
194-
flush();
195-
out.close();
196-
}
197-
198-
}
88+
}

0 commit comments

Comments
 (0)