Java IO流之StringWriter和StringReader用法分析

网友投稿 260 2022-11-16

Java IO流之StringWriter和StringReader用法分析

简介

StringWriter和StringReader分别继承自Writer和Reader抽象类,作用就是将字符串String类型适配到StringWriter和StringReader类.

其中StringWriter实际上是用StringBuffer实现的,StringBuffer是一个线程安全的类,实际上默认的是16个字符的char数组.所以通过方法write()和append()等其他重载的方法.将字符串添加到StringBuffer中,可以调用toString()或者getBuffer()方法显示StringWriter流中所有的数据.其中close()方法和flush()方法,无实际的功能,只是简单的继承.

StringReader的有参构造方法传入的是String类型的数据,通过read()重载方法读取流中部分或者全部的字符内容.

StringWriter介绍

1.构造方法

public StringWriter() {}

public StringWriter(int initialSize) {}

无参构造方法,创建的是默认大小为StringBuffer的StringWriter流,其中StringBuffer底层实际是一个字符数组,默认大小是16个字符.

有参构造方法,创建的是指定大小的StringBuffer的StringWriter流,也就是指定initialSize个字符的字符数组.

2.内部变量

private StringBuffer buf;

StringWriter流中缓冲区实际上通过StringBuffer来实现的.

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() {}

write(int c)---将单个字符写到流中.

write(char cbuf[] ,int off,int len)---将字符数组cbuf中NYPkMTWoff开始,len个字符写到流中.

write(String str)---将字符串str写到流中.

write(String str,int off,int len)---将字符串str中off位置开始,len个字符写到流中.

append(charsequence csq)---将字符序列csq写到流中.

append(charsequence csq,int start ,int end)----将字符序列中start到end之间字符写到流中.

append(char c)---将单个字符写到流中.

toString()---将流中所有字符转换成字符串返回.

getBuffer()----将流中内容,实际是StringBuffer返回.

flush()---仅仅是继承,方法内没有任何实现.

close()----仅仅是继承,方法内没有任何实现.

StringReader介绍

1.构造方法

public StringReader(String s) {}

有参构造方法,传入的实际上是流中内容为字符串s.

2.内部变量

private String str;

private int length;

private int next = 0;

private int mark = 0;

str---StringReader流中实际的数据就是通过构造方法传入的字符串str.

length---流中字符串的长度.

http:// next---要读取的下一个字符的位置.

mark---标记字符位置,调用mark()方法会将当前位置保存到mark中.

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(){}

ensureOpen()---确保流没有关闭,实际判断是流中内容字符串str不为null.

read()---从流中读取一个字符.

read(char cbuf[],int off,int len)---将流中最多len个字符读取到字符数组cbuf中,cbuf中从off开始.

skip(long ns)---跳过ns个字符.

ready()---流是否准备读取.

markSupported()---是否支持标记

mark(int readAheadLimit)---标记当前位置,readAheadLimit表示的是在标记有效情况下,从当前位置开始可取的最大字符数.

reset()---将流中当前位置重置到标记位置.

close()---关闭流,实际上是将流中内容字符串str置为null.

案例

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)) {

http:// 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;

}

}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:[数据仓库]kettle——入门操作(文本文件输入流)
下一篇:Windows程序设计-鼠标
相关文章

 发表评论

暂时没有评论,来抢沙发吧~