StringWriter和StringReader分别继承自Writer和Reader抽象类,作用就是将字符串String类型适配到StringWriter和StringReader类.
其中StringWriter实际上是用StringBuffer实现的,StringBuffer是一个线程安全的类,实际上默认的是16个字符的char数组.所以通过方法write()和append()等其他重载的方法.将字符串添加到StringBuffer中,可以调用toString()或者getBuffer()方法显示StringWriter流中所有的数据.其中close()方法和flush()方法,无实际的功能,只是简单的继承.
StringReader的有参构造方法传入的是String类型的数据,通过read()重载方法读取流中部分或者全部的字符内容.
1.构造方法
public StringWriter() {}
public StringWriter(int initialSize) {}
2.内部变量
private StringBuffer buf;
3. 内部方法
public void write(int c) {}
public void write(char cbuf[], int off, int len){}
public void write(String str) {}
public void write(String str, int off, int len){}
public StringWriter append(CharSequence csq){}
public StringWriter append(CharSequence csq, int start, int end){}
public StringWriter append(char c){}
public String toString() {}
public StringBuffer getBuffer() {}
public void flush() {}
public void close() {}
1.构造方法
public StringReader(String s) {}
2.内部变量
private String str;
private int length;
private int next = 0;
private int mark = 0;
3. 内部方法
private void ensureOpen(){}
public int read(){}
public int read(char cbuf[], int off, int len){}
public long skip(long ns){}
public boolean ready(){}
public boolean markSupported() {}
public void mark(int readAheadLimit){}
public void reset(){}
public void close(){}
public class StringWriterDemo {
public static void main(String[] args) throws IOException {
testStringWriter();
testStringReader();
testOfAnotherStringWriter();
}
//测试StringWriter
private static void testStringWriter() throws IOException {
StringWriter sw = new StringWriter();
sw.append("this is a");
sw.write("demo of StringWriter");
System.out.println(sw.toString());
sw.close();
}
//测试StringReader
private static void testStringReader() throws IOException {
String content = "this is a demo of StringReader";
StringReader sr = new StringReader(content);
int c;
while((c=sr.read())!=-1) {
System.out.println((char)c);
}
sr.close();
}
//将读取的数据先写到StringWriter流中,然后直接调用toString()方法打印结果
private static void testOfAnotherStringWriter() throws IOException {
FileReader fr = new FileReader("D:\\java.txt");
BufferedReader br = new BufferedReader(fr);
StringWriter sw = new StringWriter();
int n;
char cbuf[] = new char[1024];
while((n=br.read(cbuf))!=-1) {
sw.write(cbuf, 0, n);
}
System.out.println(sw.toString());
fr.close();
br.close();
}
}
1.StringWriter源码分析
public class StringWriter extends Writer {
//StringWriter中缓冲功能是通过StringBuffer来实现的.
private StringBuffer buf;
//创建默认缓冲为16个字符的StringWriter.默认的StringBuffer实际是大小为16个字符的字符数组.
public StringWriter() {
buf = new StringBuffer();
lock = buf;
}
//创建指定大小StringBuffer的StringWriter,也就是指定了initialSize个字符的字符数组.
public StringWriter(int initialSize) {
if (initialSize < 0) {
throw new IllegalArgumentException("Negative buffer size");
}
buf = new StringBuffer(initialSize);
lock = buf;
}
//向流写入单个字符c
public void write(int c) {
buf.append((char) c);
}
//将字符数组cbuf中off位置开始,len个字符写到流中
public void write(char cbuf[], int off, int len) {
if ((off < 0) || (off > cbuf.length) || (len < 0) ||
((off + len) > cbuf.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return;
}
buf.append(cbuf, off, len);
}
//将字符串str写到流中
public void write(String str) {
buf.append(str);
}
//将字符串str中off位置开始,len个字符写到流中
public void write(String str, int off, int len) {
buf.append(str.substring(off, off + len));
}
//将字符序列csq添加到流中.
public StringWriter append(CharSequence csq) {
if (csq == null)
write("null");
else
write(csq.toString());
return this;
}
//将字符序列csq中start位置到end之间的字符添加到流中
public StringWriter append(CharSequence csq, int start, int end) {
CharSequence cs = (csq == null ? "null" : csq);
write(cs.subSequence(start, end).toString());
return this;
}
//向流中添加一个字符c
public StringWriter append(char c) {
write(c);
return this;
}
//将流中字符转换成字符串返回.
public String toString() {
return buf.toString();
}
//返回流的内容,即StringBuffer
public StringBuffer getBuffer() {
return buf;
}
//刷新流,没有具体实现.
public void flush() {
}
//关闭流后读取数据不会抛出异常,因为没有具体实现
public void close() throws IOException {
}
}
2,StringReader源码分析
public class StringReader extends Reader {
//流中实际数据就是通过构造方法传入str字符串.
private String str;
//字符串str的长度
private int length;
//下一个要读取字符的位置.
private int next = 0;
//标记的位置.
private int mark = 0;
//创建一个StringReader流,参数传入的是字符串s
public StringReader(String s) {
this.str = s;
this.length = s.length();
}
//确保流没有关闭,实际判断的是StringReader构造方法是否有传入字符串.
private void ensureOpen() throws IOException {
if (str == null)
throw new IOException("Stream closed");
}
//读取单个字符
public int read() throws IOException {
synchronized (lock) {
ensureOpen();
if (next >= length)
return -1;
return str.charAt(next++);
}
}
//将缓冲区中最多len个字符写到字符数组cbuf中,位置从off开始,长度为len个
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;
}
//超过字符串的长度,返回-1
if (next >= length)
return -1;
//剩余可读取的字符为length-next,
//如果len超过剩余可读取字符,实际只能读取剩余可读取字符
//如果len小于剩余可读取字符,实际上读取的是len个字符
int n = Math.min(length - next, len);
str.getChars(next, next + n, cbuf, off);
next += n;
return n;
}
}
//跳过ns个字符,返回跳过的字符数
public long skip(long ns) throws IOException {
synchronized (lock) {
ensureOpen();
if (next >= length)
return 0;
// Bound skip by beginning and end of the source
//缓冲区中剩余字符数与要跳过的字符数比较.取较小值
long n = Math.min(length - next, ns);
n = Math.max(-next, n);
next += n;
return n;
}
}
//流是否准备读取.
public boolean ready() throws IOException {
synchronized (lock) {
ensureOpen();
return true;
}
}
//流是否支持标记
public boolean markSupported() {
return true;
}
//标记缓冲区中当前位置,readAheadLimit表示的是在保留标记的情况下,最大可读取的字符数
public void mark(int readAheadLimit) throws IOException {
if (readAheadLimit < 0){
throw new IllegalArgumentException("Read-ahead limit < 0");
}
synchronized (lock) {
ensureOpen();
mark = next;
}
}
//将缓冲区当前位置重置到标记位置
public void reset() throws IOException {
synchronized (lock) {
ensureOpen();
next = mark;
}
}
//关闭流,释放相关资源(实际只是将流中内容字符串置为空)
public void close() {
str = null;
}
}