Author: niallp
Date: Fri Dec 5 14:42:34 2008
New Revision: 723912
URL: http://svn.apache.org/viewvc?rev=723912&view=rev
Log:
IO-158 New ReaderInputStream and WriterOutputStream implementations - thanks to
Andreas Veithen for the patch
Added:
commons/proper/io/trunk/src/java/org/apache/commons/io/input/ReaderInputStream.java
(with props)
commons/proper/io/trunk/src/java/org/apache/commons/io/output/WriterOutputStream.java
(with props)
commons/proper/io/trunk/src/test/org/apache/commons/io/input/ReaderInputStreamTest.java
(with props)
commons/proper/io/trunk/src/test/org/apache/commons/io/output/WriterOutputStreamTest.java
(with props)
Added:
commons/proper/io/trunk/src/java/org/apache/commons/io/input/ReaderInputStream.java
URL:
http://svn.apache.org/viewvc/commons/proper/io/trunk/src/java/org/apache/commons/io/input/ReaderInputStream.java?rev=723912&view=auto
==============================================================================
---
commons/proper/io/trunk/src/java/org/apache/commons/io/input/ReaderInputStream.java
(added)
+++
commons/proper/io/trunk/src/java/org/apache/commons/io/input/ReaderInputStream.java
Fri Dec 5 14:42:34 2008
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.io.input;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+
+/**
+ * [EMAIL PROTECTED] InputStream} implementation that reads a character stream
from a [EMAIL PROTECTED] Reader}
+ * and transforms it to a byte stream using a specified charset encoding. The
stream
+ * is transformed using a [EMAIL PROTECTED] CharsetEncoder} object,
guaranteeing that all charset
+ * encodings supported by the JRE are handled correctly. In particular for
charsets such as
+ * UTF-16, the implementation ensures that one and only one byte order marker
+ * is produced.
+ * <p>
+ * Since in general it is not possible to predict the number of characters to
be read from the
+ * [EMAIL PROTECTED] Reader} to satisfy a read request on the [EMAIL
PROTECTED] ReaderInputStream}, all reads from
+ * the [EMAIL PROTECTED] Reader} are buffered. There is therefore no well
defined correlation
+ * between the current position of the [EMAIL PROTECTED] Reader} and that of
the [EMAIL PROTECTED] ReaderInputStream}.
+ * This also implies that in general there is no need to wrap the underlying
[EMAIL PROTECTED] Reader}
+ * in a [EMAIL PROTECTED] java.io.BufferedReader}.
+ * <p>
+ * [EMAIL PROTECTED] ReaderInputStream} implements the inverse transformation
of [EMAIL PROTECTED] java.io.InputStreamReader};
+ * in the following example, reading from <tt>in2</tt> would return the same
byte
+ * sequence as reading from <tt>in</tt> (provided that the initial byte
sequence is legal
+ * with respect to the charset encoding):
+ * <pre>
+ * InputStream in = ...
+ * Charset cs = ...
+ * InputStreamReader reader = new InputStreamReader(in, cs);
+ * ReaderInputStream in2 = new ReaderInputStream(reader, cs);</pre>
+ * [EMAIL PROTECTED] ReaderInputStream} implements the same transformation as
[EMAIL PROTECTED] java.io.OutputStreamWriter},
+ * except that the control flow is reversed: both classes transform a
character stream
+ * into a byte stream, but [EMAIL PROTECTED] java.io.OutputStreamWriter}
pushes data to the underlying stream,
+ * while [EMAIL PROTECTED] ReaderInputStream} pulls it from the underlying
stream.
+ * <p>
+ * Note that while there are use cases where there is no alternative to using
+ * this class, very often the need to use this class is an indication of a flaw
+ * in the design of the code. This class is typically used in situations where
an existing
+ * API only accepts an [EMAIL PROTECTED] InputStream}, but where the most
natural way to produce the data
+ * is as a character stream, i.e. by providing a [EMAIL PROTECTED] Reader}
instance. An example of a situation
+ * where this problem may appear is when implementing the [EMAIL PROTECTED]
javax.activation.DataSource}
+ * interface from the Java Activation Framework.
+ * <p>
+ * Given the fact that the [EMAIL PROTECTED] Reader} class doesn't provide any
way to predict whether the next
+ * read operation will block or not, it is not possible to provide a meaningful
+ * implementation of the [EMAIL PROTECTED] InputStream#available()} method. A
call to this method
+ * will always return 0. Also, this class doesn't support [EMAIL PROTECTED]
InputStream#mark(int)}.
+ * <p>
+ * Instances of [EMAIL PROTECTED] ReaderInputStream} are not thread safe.
+ *
+ * @see org.apache.commons.io.output.WriterOutputStream
+ *
+ * @author <a href="mailto:[EMAIL PROTECTED]">Andreas Veithen</a>
+ * @since Commons IO 2.0
+ */
+public class ReaderInputStream extends InputStream {
+ private static final int DEFAULT_BUFFER_SIZE = 1024;
+
+ private final Reader reader;
+ private final CharsetEncoder encoder;
+
+ /**
+ * CharBuffer used as input for the decoder. It should be reasonably
+ * large as we read data from the underlying Reader into this buffer.
+ */
+ private final CharBuffer encoderIn;
+
+ /**
+ * ByteBuffer used as output for the decoder. This buffer can be small
+ * as it is only used to transfer data from the decoder to the
+ * buffer provided by the caller.
+ */
+ private final ByteBuffer encoderOut = ByteBuffer.allocate(128);
+
+ private CoderResult lastCoderResult;
+ private boolean endOfInput;
+
+ /**
+ * Construct a new [EMAIL PROTECTED] ReaderInputStream}.
+ *
+ * @param reader the target [EMAIL PROTECTED] Reader}
+ * @param charset the charset encoding
+ * @param bufferSize the size of the input buffer in number of characters
+ */
+ public ReaderInputStream(Reader reader, Charset charset, int bufferSize) {
+ this.reader = reader;
+ encoder = charset.newEncoder();
+ encoderIn = CharBuffer.allocate(bufferSize);
+ encoderIn.flip();
+ }
+
+ /**
+ * Construct a new [EMAIL PROTECTED] ReaderInputStream} with a default
input buffer size of
+ * 1024 characters.
+ *
+ * @param reader the target [EMAIL PROTECTED] Reader}
+ * @param charset the charset encoding
+ */
+ public ReaderInputStream(Reader reader, Charset charset) {
+ this(reader, charset, DEFAULT_BUFFER_SIZE);
+ }
+
+ /**
+ * Construct a new [EMAIL PROTECTED] ReaderInputStream}.
+ *
+ * @param reader the target [EMAIL PROTECTED] Reader}
+ * @param charsetName the name of the charset encoding
+ * @param bufferSize the size of the input buffer in number of characters
+ */
+ public ReaderInputStream(Reader reader, String charsetName, int
bufferSize) {
+ this(reader, Charset.forName(charsetName), bufferSize);
+ }
+
+ /**
+ * Construct a new [EMAIL PROTECTED] ReaderInputStream} with a default
input buffer size of
+ * 1024 characters.
+ *
+ * @param reader the target [EMAIL PROTECTED] Reader}
+ * @param charsetName the name of the charset encoding
+ */
+ public ReaderInputStream(Reader reader, String charsetName) {
+ this(reader, charsetName, DEFAULT_BUFFER_SIZE);
+ }
+
+ /**
+ * Construct a new [EMAIL PROTECTED] ReaderInputStream} that uses the
default character encoding
+ * with a default input buffer size of 1024 characters.
+ *
+ * @param reader the target [EMAIL PROTECTED] Reader}
+ */
+ public ReaderInputStream(Reader reader) {
+ this(reader, Charset.defaultCharset());
+ }
+
+ /**
+ * Read the specified number of bytes into an array.
+ *
+ * @param b the byte array to read into
+ * @param off the offset to start reading bytes into
+ * @param len the number of bytes to read
+ * @return the number of bytes read or <code>-1</code>
+ * if the end of the stream has been reached
+ * @throws IOException if an I/O error occurs
+ */
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ int read = 0;
+ while (len > 0) {
+ if (encoderOut.position() > 0) {
+ encoderOut.flip();
+ int c = Math.min(encoderOut.remaining(), len);
+ encoderOut.get(b, off, c);
+ off += c;
+ len -= c;
+ read += c;
+ encoderOut.compact();
+ } else {
+ if (!endOfInput && (lastCoderResult == null ||
lastCoderResult.isUnderflow())) {
+ encoderIn.compact();
+ int position = encoderIn.position();
+ // We don't use Reader#read(CharBuffer) here because it is
more efficient
+ // to write directly to the underlying char array (the
default implementation
+ // copies data to a temporary char array).
+ int c = reader.read(encoderIn.array(), position,
encoderIn.remaining());
+ if (c == -1) {
+ endOfInput = true;
+ } else {
+ encoderIn.position(position+c);
+ }
+ encoderIn.flip();
+ }
+ lastCoderResult = encoder.encode(encoderIn, encoderOut,
endOfInput);
+ if (endOfInput && encoderOut.position() == 0) {
+ break;
+ }
+ }
+ }
+ return read == 0 && endOfInput ? -1 : read;
+ }
+
+ /**
+ * Read the specified number of bytes into an array.
+ *
+ * @param b the byte array to read into
+ * @return the number of bytes read or <code>-1</code>
+ * if the end of the stream has been reached
+ * @throws IOException if an I/O error occurs
+ */
+ @Override
+ public int read(byte[] b) throws IOException {
+ return read(b, 0, b.length);
+ }
+
+ /**
+ * Read a single byte.
+ *
+ * @return either the byte read or <code>-1</code> if the end of the stream
+ * has been reached
+ * @throws IOException if an I/O error occurs
+ */
+ @Override
+ public int read() throws IOException {
+ byte[] b = new byte[1];
+ return read(b) == -1 ? -1 : b[0] & 0xFF;
+ }
+
+ /**
+ * Close the stream. This method will cause the underlying [EMAIL
PROTECTED] Reader}
+ * to be closed.
+ * @throws IOException if an I/O error occurs
+ */
+ @Override
+ public void close() throws IOException {
+ reader.close();
+ }
+}
Propchange:
commons/proper/io/trunk/src/java/org/apache/commons/io/input/ReaderInputStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
commons/proper/io/trunk/src/java/org/apache/commons/io/input/ReaderInputStream.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision
Added:
commons/proper/io/trunk/src/java/org/apache/commons/io/output/WriterOutputStream.java
URL:
http://svn.apache.org/viewvc/commons/proper/io/trunk/src/java/org/apache/commons/io/output/WriterOutputStream.java?rev=723912&view=auto
==============================================================================
---
commons/proper/io/trunk/src/java/org/apache/commons/io/output/WriterOutputStream.java
(added)
+++
commons/proper/io/trunk/src/java/org/apache/commons/io/output/WriterOutputStream.java
Fri Dec 5 14:42:34 2008
@@ -0,0 +1,274 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.io.output;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+
+/**
+ * [EMAIL PROTECTED] OutputStream} implementation that transforms a byte
stream to a
+ * character stream using a specified charset encoding and writes the resulting
+ * stream to a [EMAIL PROTECTED] Writer}. The stream is transformed using a
+ * [EMAIL PROTECTED] CharsetDecoder} object, guaranteeing that all charset
+ * encodings supported by the JRE are handled correctly.
+ * <p>
+ * The output of the [EMAIL PROTECTED] CharsetDecoder} is buffered using a
fixed size buffer.
+ * This implies that the data is written to the underlying [EMAIL PROTECTED]
Writer} in chunks
+ * that are no larger than the size of this buffer. By default, the buffer is
+ * flushed only when it overflows or when [EMAIL PROTECTED] #flush()} or
[EMAIL PROTECTED] #close()}
+ * is called. In general there is therefore no need to wrap the underlying
[EMAIL PROTECTED] Writer}
+ * in a [EMAIL PROTECTED] java.io.BufferedWriter}. [EMAIL PROTECTED]
WriterOutputStream} can also
+ * be instructed to flush the buffer after each write operation. In this case,
all
+ * available data is written immediately to the underlying [EMAIL PROTECTED]
Writer}, implying that
+ * the current position of the [EMAIL PROTECTED] Writer} is correlated to the
current position
+ * of the [EMAIL PROTECTED] WriterOutputStream}.
+ * <p>
+ * [EMAIL PROTECTED] WriterOutputStream} implements the inverse transformation
of [EMAIL PROTECTED] java.io.OutputStreamWriter};
+ * in the following example, writing to <tt>out2</tt> would have the same
result as writing to
+ * <tt>out</tt> directly (provided that the byte sequence is legal with
respect to the
+ * charset encoding):
+ * <pre>
+ * OutputStream out = ...
+ * Charset cs = ...
+ * OutputStreamWriter writer = new OutputStreamWriter(out, cs);
+ * WriterOutputStream out2 = new WriterOutputStream(writer, cs);</pre>
+ * [EMAIL PROTECTED] WriterOutputStream} implements the same transformation as
[EMAIL PROTECTED] java.io.InputStreamReader},
+ * except that the control flow is reversed: both classes transform a byte
stream
+ * into a character stream, but [EMAIL PROTECTED] java.io.InputStreamReader}
pulls data from the underlying stream,
+ * while [EMAIL PROTECTED] WriterOutputStream} pushes it to the underlying
stream.
+ * <p>
+ * Note that while there are use cases where there is no alternative to using
+ * this class, very often the need to use this class is an indication of a flaw
+ * in the design of the code. This class is typically used in situations where
an existing
+ * API only accepts an [EMAIL PROTECTED] OutputStream} object, but where the
stream is known to represent
+ * character data that must be decoded for further use.
+ * <p>
+ * Instances of [EMAIL PROTECTED] WriterOutputStream} are not thread safe.
+ *
+ * @see org.apache.commons.io.input.ReaderInputStream
+ *
+ * @author <a href="mailto:[EMAIL PROTECTED]">Andreas Veithen</a>
+ * @since Commons IO 2.0
+ */
+public class WriterOutputStream extends OutputStream {
+ private static final int DEFAULT_BUFFER_SIZE = 1024;
+
+ private final Writer writer;
+ private final CharsetDecoder decoder;
+ private final boolean writeImmediately;
+
+ /**
+ * ByteBuffer used as input for the decoder. This buffer can be small
+ * as it is used only to transfer the received data to the
+ * decoder.
+ */
+ private final ByteBuffer decoderIn = ByteBuffer.allocate(128);
+
+ /**
+ * CharBuffer used as output for the decoder. It should be
+ * somewhat larger as we write from this buffer to the
+ * underlying Writer.
+ */
+ private final CharBuffer decoderOut;
+
+ /**
+ * Constructs a new [EMAIL PROTECTED] WriterOutputStream}.
+ *
+ * @param writer the target [EMAIL PROTECTED] Writer}
+ * @param charset the charset encoding
+ * @param bufferSize the size of the output buffer in number of characters
+ * @param writeImmediately If <tt>true</tt> the output buffer will be
flushed after each
+ * write operation, i.e. all available data will
be written to the
+ * underlying [EMAIL PROTECTED] Writer}
immediately. If <tt>false</tt>, the
+ * output buffer will only be flushed when it
overflows or when
+ * [EMAIL PROTECTED] #flush()} or [EMAIL
PROTECTED] #close()} is called.
+ */
+ public WriterOutputStream(Writer writer, Charset charset, int bufferSize,
boolean writeImmediately) {
+ this.writer = writer;
+ decoder = charset.newDecoder();
+ decoder.onMalformedInput(CodingErrorAction.REPLACE);
+ decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ decoder.replaceWith("?");
+ this.writeImmediately = writeImmediately;
+ decoderOut = CharBuffer.allocate(bufferSize);
+ }
+
+ /**
+ * Constructs a new [EMAIL PROTECTED] WriterOutputStream} with a default
output buffer size of
+ * 1024 characters. The output buffer will only be flushed when it
overflows or when
+ * [EMAIL PROTECTED] #flush()} or [EMAIL PROTECTED] #close()} is called.
+ *
+ * @param writer the target [EMAIL PROTECTED] Writer}
+ * @param charset the charset encoding
+ */
+ public WriterOutputStream(Writer writer, Charset charset) {
+ this(writer, charset, DEFAULT_BUFFER_SIZE, false);
+ }
+
+ /**
+ * Constructs a new [EMAIL PROTECTED] WriterOutputStream}.
+ *
+ * @param writer the target [EMAIL PROTECTED] Writer}
+ * @param charsetName the name of the charset encoding
+ * @param bufferSize the size of the output buffer in number of characters
+ * @param writeImmediately If <tt>true</tt> the output buffer will be
flushed after each
+ * write operation, i.e. all available data will
be written to the
+ * underlying [EMAIL PROTECTED] Writer}
immediately. If <tt>false</tt>, the
+ * output buffer will only be flushed when it
overflows or when
+ * [EMAIL PROTECTED] #flush()} or [EMAIL
PROTECTED] #close()} is called.
+ */
+ public WriterOutputStream(Writer writer, String charsetName, int
bufferSize, boolean writeImmediately) {
+ this(writer, Charset.forName(charsetName), bufferSize,
writeImmediately);
+ }
+
+ /**
+ * Constructs a new [EMAIL PROTECTED] WriterOutputStream} with a default
output buffer size of
+ * 1024 characters. The output buffer will only be flushed when it
overflows or when
+ * [EMAIL PROTECTED] #flush()} or [EMAIL PROTECTED] #close()} is called.
+ *
+ * @param writer the target [EMAIL PROTECTED] Writer}
+ * @param charsetName the name of the charset encoding
+ */
+ public WriterOutputStream(Writer writer, String charsetName) {
+ this(writer, charsetName, DEFAULT_BUFFER_SIZE, false);
+ }
+
+ /**
+ * Constructs a new [EMAIL PROTECTED] WriterOutputStream} that uses the
default character encoding
+ * and with a default output buffer size of 1024 characters. The output
buffer will only
+ * be flushed when it overflows or when [EMAIL PROTECTED] #flush()} or
[EMAIL PROTECTED] #close()} is called.
+ *
+ * @param writer the target [EMAIL PROTECTED] Writer}
+ */
+ public WriterOutputStream(Writer writer) {
+ this(writer, Charset.defaultCharset(), DEFAULT_BUFFER_SIZE, false);
+ }
+
+ /**
+ * Write bytes from the specified byte array to the stream.
+ *
+ * @param b the byte array containing the bytes to write
+ * @param off the start offset in the byte array
+ * @param len the number of bytes to write
+ * @throws IOException if an I/O error occurs
+ */
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException {
+ while (len > 0) {
+ int c = Math.min(len, decoderIn.remaining());
+ decoderIn.put(b, off, c);
+ processInput(false);
+ len -= c;
+ off += c;
+ }
+ if (writeImmediately) {
+ flushOutput();
+ }
+ }
+
+ /**
+ * Write bytes from the specified byte array to the stream.
+ *
+ * @param b the byte array containing the bytes to write
+ * @throws IOException if an I/O error occurs
+ */
+ @Override
+ public void write(byte[] b) throws IOException {
+ write(b, 0, b.length);
+ }
+
+ /**
+ * Write a single byte to the stream.
+ *
+ * @param b the byte to write
+ * @throws IOException if an I/O error occurs
+ */
+ @Override
+ public void write(int b) throws IOException {
+ write(new byte[] { (byte)b }, 0, 1);
+ }
+
+ /**
+ * Flush the stream. Any remaining content accumulated in the output buffer
+ * will be written to the underlying [EMAIL PROTECTED] Writer}. After that
+ * [EMAIL PROTECTED] Writer#flush()} will be called.
+ * @throws IOException if an I/O error occurs
+ */
+ @Override
+ public void flush() throws IOException {
+ flushOutput();
+ writer.flush();
+ }
+
+ /**
+ * Close the stream. Any remaining content accumulated in the output buffer
+ * will be written to the underlying [EMAIL PROTECTED] Writer}. After that
+ * [EMAIL PROTECTED] Writer#close()} will be called.
+ * @throws IOException if an I/O error occurs
+ */
+ @Override
+ public void close() throws IOException {
+ processInput(true);
+ flushOutput();
+ writer.close();
+ }
+
+ /**
+ * Decode the contents of the input ByteBuffer into a CharBuffer.
+ *
+ * @param endOfInput indicates end of input
+ * @throws IOException if an I/O error occurs
+ */
+ private void processInput(boolean endOfInput) throws IOException {
+ // Prepare decoderIn for reading
+ decoderIn.flip();
+ CoderResult coderResult;
+ while (true) {
+ coderResult = decoder.decode(decoderIn, decoderOut, endOfInput);
+ if (coderResult.isOverflow()) {
+ flushOutput();
+ } else if (coderResult.isUnderflow()) {
+ break;
+ } else {
+ // The decoder is configured to replace malformed input and
unmappable characters,
+ // so we should not get here.
+ throw new IOException("Unexpected coder result");
+ }
+ }
+ // Discard the bytes that have been read
+ decoderIn.compact();
+ }
+
+ /**
+ * Flush the output.
+ *
+ * @throws IOException if an I/O error occurs
+ */
+ private void flushOutput() throws IOException {
+ if (decoderOut.position() > 0) {
+ writer.write(decoderOut.array(), 0, decoderOut.position());
+ decoderOut.rewind();
+ }
+ }
+}
Propchange:
commons/proper/io/trunk/src/java/org/apache/commons/io/output/WriterOutputStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
commons/proper/io/trunk/src/java/org/apache/commons/io/output/WriterOutputStream.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision
Added:
commons/proper/io/trunk/src/test/org/apache/commons/io/input/ReaderInputStreamTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/io/trunk/src/test/org/apache/commons/io/input/ReaderInputStreamTest.java?rev=723912&view=auto
==============================================================================
---
commons/proper/io/trunk/src/test/org/apache/commons/io/input/ReaderInputStreamTest.java
(added)
+++
commons/proper/io/trunk/src/test/org/apache/commons/io/input/ReaderInputStreamTest.java
Fri Dec 5 14:42:34 2008
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.io.input;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Random;
+
+import junit.framework.TestCase;
+
+public class ReaderInputStreamTest extends TestCase {
+ private static final String TEST_STRING = "\u00e0 peine arriv\u00e9s nous
entr\u00e2mes dans sa chambre";
+ private static final String LARGE_TEST_STRING;
+
+ static {
+ StringBuilder buffer = new StringBuilder();
+ for (int i=0; i<100; i++) {
+ buffer.append(TEST_STRING);
+ }
+ LARGE_TEST_STRING = buffer.toString();
+ }
+
+ private Random random = new Random();
+
+ private void testWithSingleByteRead(String testString, String charsetName)
throws IOException {
+ byte[] bytes = testString.getBytes(charsetName);
+ ReaderInputStream in = new ReaderInputStream(new
StringReader(testString), charsetName);
+ for (int i=0; i<bytes.length; i++) {
+ int read = in.read();
+ assertTrue(read >= 0);
+ assertTrue(read <= 255);
+ assertEquals(bytes[i], (byte)read);
+ }
+ assertEquals(-1, in.read());
+ }
+
+ private void testWithBufferedRead(String testString, String charsetName)
throws IOException {
+ byte[] expected = testString.getBytes(charsetName);
+ ReaderInputStream in = new ReaderInputStream(new
StringReader(testString), charsetName);
+ byte[] buffer = new byte[128];
+ int offset = 0;
+ while (true) {
+ int bufferOffset = random.nextInt(64);
+ int bufferLength = random.nextInt(64);
+ int read = in.read(buffer, bufferOffset, bufferLength);
+ if (read == -1) {
+ assertEquals(offset, expected.length);
+ break;
+ } else {
+ assertTrue(read <= bufferLength);
+ while (read > 0) {
+ assertTrue(offset < expected.length);
+ assertEquals(expected[offset], buffer[bufferOffset]);
+ offset++;
+ bufferOffset++;
+ read--;
+ }
+ }
+ }
+ }
+
+ public void testUTF8WithSingleByteRead() throws IOException {
+ testWithSingleByteRead(TEST_STRING, "UTF-8");
+ }
+
+ public void testLargeUTF8WithSingleByteRead() throws IOException {
+ testWithSingleByteRead(LARGE_TEST_STRING, "UTF-8");
+ }
+
+ public void testUTF8WithBufferedRead() throws IOException {
+ testWithBufferedRead(TEST_STRING, "UTF-8");
+ }
+
+ public void testLargeUTF8WithBufferedRead() throws IOException {
+ testWithBufferedRead(LARGE_TEST_STRING, "UTF-8");
+ }
+
+ public void testUTF16WithSingleByteRead() throws IOException {
+ testWithSingleByteRead(TEST_STRING, "UTF-16");
+ }
+
+ public void testReadZero() throws Exception {
+ ReaderInputStream r = new ReaderInputStream(new StringReader("test"));
+ byte[] bytes = new byte[30];
+ assertEquals(0, r.read(bytes, 0, 0));
+ }
+}
Propchange:
commons/proper/io/trunk/src/test/org/apache/commons/io/input/ReaderInputStreamTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
commons/proper/io/trunk/src/test/org/apache/commons/io/input/ReaderInputStreamTest.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision
Added:
commons/proper/io/trunk/src/test/org/apache/commons/io/output/WriterOutputStreamTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/io/trunk/src/test/org/apache/commons/io/output/WriterOutputStreamTest.java?rev=723912&view=auto
==============================================================================
---
commons/proper/io/trunk/src/test/org/apache/commons/io/output/WriterOutputStreamTest.java
(added)
+++
commons/proper/io/trunk/src/test/org/apache/commons/io/output/WriterOutputStreamTest.java
Fri Dec 5 14:42:34 2008
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.io.output;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.Random;
+
+import junit.framework.TestCase;
+
+public class WriterOutputStreamTest extends TestCase {
+ private static final String TEST_STRING = "\u00e0 peine arriv\u00e9s nous
entr\u00e2mes dans sa chambre";
+ private static final String LARGE_TEST_STRING;
+
+ static {
+ StringBuilder buffer = new StringBuilder();
+ for (int i=0; i<100; i++) {
+ buffer.append(TEST_STRING);
+ }
+ LARGE_TEST_STRING = buffer.toString();
+ }
+
+ private Random random = new Random();
+
+ private void testWithSingleByteWrite(String testString, String
charsetName) throws IOException {
+ byte[] bytes = testString.getBytes(charsetName);
+ StringWriter writer = new StringWriter();
+ WriterOutputStream out = new WriterOutputStream(writer, charsetName);
+ for (int i=0; i<bytes.length; i++) {
+ out.write(bytes[i]);
+ }
+ out.close();
+ assertEquals(testString, writer.toString());
+ }
+
+ private void testWithBufferedWrite(String testString, String charsetName)
throws IOException {
+ byte[] expected = testString.getBytes(charsetName);
+ StringWriter writer = new StringWriter();
+ WriterOutputStream out = new WriterOutputStream(writer, charsetName);
+ int offset = 0;
+ while (offset < expected.length) {
+ int length = Math.min(random.nextInt(128), expected.length-offset);
+ out.write(expected, offset, length);
+ offset += length;
+ }
+ out.close();
+ assertEquals(testString, writer.toString());
+ }
+
+ public void testUTF8WithSingleByteWrite() throws IOException {
+ testWithSingleByteWrite(TEST_STRING, "UTF-8");
+ }
+
+ public void testLargeUTF8WithSingleByteWrite() throws IOException {
+ testWithSingleByteWrite(LARGE_TEST_STRING, "UTF-8");
+ }
+
+ public void testUTF8WithBufferedWrite() throws IOException {
+ testWithBufferedWrite(TEST_STRING, "UTF-8");
+ }
+
+ public void testLargeUTF8WithBufferedWrite() throws IOException {
+ testWithBufferedWrite(LARGE_TEST_STRING, "UTF-8");
+ }
+
+ public void testUTF16WithSingleByteWrite() throws IOException {
+ testWithSingleByteWrite(TEST_STRING, "UTF-16");
+ }
+
+ public void testFlush() throws IOException {
+ StringWriter writer = new StringWriter();
+ WriterOutputStream out = new WriterOutputStream(writer, "us-ascii",
1024, false);
+ out.write("abc".getBytes("us-ascii"));
+ assertEquals(0, writer.getBuffer().length());
+ out.flush();
+ assertEquals("abc", writer.toString());
+ }
+
+ public void testWriteImmediately() throws IOException {
+ StringWriter writer = new StringWriter();
+ WriterOutputStream out = new WriterOutputStream(writer, "us-ascii",
1024, true);
+ out.write("abc".getBytes("us-ascii"));
+ assertEquals("abc", writer.toString());
+ }
+}
Propchange:
commons/proper/io/trunk/src/test/org/apache/commons/io/output/WriterOutputStreamTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
commons/proper/io/trunk/src/test/org/apache/commons/io/output/WriterOutputStreamTest.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision