7、字符串流 StringReader和StringWriter
7.1 StringReader
StringReader在构造时会传入一个字符串作为源,并且支持mark方法
private String str; private int length; private int next = 0;//指向下一个可读取的位置 private int mark = 0;//"书签" /*构造函数*/ public StringReader(String s) { this.str = s; this.length = s.length(); }
读取时按照字符读取。
public int read() throws IOException { synchronized (lock) { ensureOpen(); if (next >= length) return -1; return str.charAt(next++); } } public int read(char cbuf[], int off, int len) throws IOException { synchronized (lock) { ensureOpen(); if ((off < 0) || (off > cbuf.length) || (len < 0) || ((off + len) > cbuf.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } if (next >= length) return -1; int n = Math.min(length - next, len); str.getChars(next, next + n, cbuf, off); next += n; return n; } }
7.2 StringWriter
StringWriter则可以自定义字符串缓冲区大小或者使用使用默认大小。其close()方法无效,关闭后仍可调用而不会抛出异常。
private StringBuffer buf;/*字符串缓冲区*/ public StringWriter() { buf = new StringBuffer(); lock = buf; } public StringWriter(int initialSize) { if (initialSize < 0) { throw new IllegalArgumentException("Negative buffer size"); } buf = new StringBuffer(initialSize); lock = buf; }
StringWriter包含各种writer和append方法,而且可以使用toString()和getBuffer()获取已经写入的数据。
8、数组流
如果说文件流是把文件当做数据源,那么数组流则是把内存中的某个字节/字符数组对象当做数据源,文件流包含字节数组输入流ByteArrayInputStream和字节数组输出流ByteArrayOutputStream,字符数组输入流CharArrayReader和字符数组输出流CharArrayWriter。
8.1 字节数组输入流ByteArrayInputStream
java.io.ByteArrayInputStream包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪read方法要提供的下一个字节。
/*内部缓冲区*/ protected byte buf[]; /*内部计数器*/ protected int pos;
需要注意的是,关闭ByteArrayInputStream无效。此类中的方法在关闭流后仍可被调用而不会产生任何IOException。这个可以从源代码中看出来,
其构造函数只是将传入的字节数组传入到内部缓冲区,在读取的时候从缓冲区读取。而该流的close()方法什么都没有做。
/** * Closing a <tt>ByteArrayInputStream</tt> has no effect. The methods in * this class can be called after the stream has been closed without * generating an <tt>IOException</tt>. */ public void close() throws IOException { }
8.2 字节数组输出流ByteArrayOutputStream
java.io.ByteArrayOutputStream实现了一个输出流,其中的数据被写入一个byte数组,缓冲区会随着数据的不断写入而自动增长,可使用toByteArray()和toString()获取数据。同样的,关闭ByteArrayOutputStream无效。
/*内部缓冲区*/ protected byte buf[]; /*缓冲区数据个数*/ protected int count;
相比于字节数组输入流,字节数组输出流做了什么似乎就没那么明确了。
字节数组输入流ByteArrayInputStream做的是将一个字节数组封装进流中,然后我们通过字节数组输入流来读取该字节数组的数据。
而字节数组输出流ByteArrayOutputStream做的是,创建ByteArrayOutputStream实例的时候只创建了默认或指定大小的内部缓冲区,然后通过write方法将数据写入内部缓冲区(期间缓冲区会自动增长),可通过toString()和toByteArray()获取流中的数据,或者使用writeTo(OutputStream out)将数据写入到指定的输出流中。
8.3 字符数组输入流CharArrayReader
java.io.CharArrayReader实现一个可用作字符输入流的字符缓冲区。
/** The character buffer. */ protected char buf[]; /** The current buffer position. */ protected int pos; public CharArrayReader(char buf[]) { this.buf = buf; this.pos = 0; this.count = buf.length; } public CharArrayReader(char buf[], int offset, int length) { if ((offset < 0) || (offset > buf.length) || (length < 0) || ((offset + length) < 0)) { throw new IllegalArgumentException(); } this.buf = buf; this.pos = offset; this.count = Math.min(offset + length, buf.length); this.markedPos = offset; }
只是其close()会将缓冲区置空,关闭流之后不可调用。
public void close() { buf = null; }
8.4 字符数组输出流CharArrayWriter
java.io.CharArrayWriter实现一个可用作Writer的字符缓冲区。缓冲区会随向流中写入数据而自动增长。可使用toCharArray()和toString()获取数据。
该类的close()方法也是无效的,并未做任何操作。
/** * Close the stream. This method does not release the buffer, since its * contents might still be required. Note: Invoking this method in this class * will have no effect. */ public void close() { }