StringReader分析
IO流分类图

访问字符串
StringReader是字符输入流,Reader的子类,从一个String中读取,所以需要一个String ,通过构造方法传递
StringWriter是字符输出流,Writer的子类,写入到一个String中去,所以它内部提供了一个StringBuffer中用来保存数据
StringReader
1. 属性和构造方法
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(); } str :指向这个字符串 length :为字符串长度 next :为读取元素的下标索引 mark :为标记点
2. 基本方法
1. read()方法
//读取一个字符 public int read() throws IOException { synchronized (lock) { ensureOpen(); if (next >= length) return -1; return str.charAt(next++); } }
注::从中可看出StringReader 将String字符串操作 适配成 Reader字符操作 对外提供服务 —> StringReader是一个适配器类
//批量读取 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; } }
2. 标记相关方法
//判断是否支持标记 public boolean markSupported() { return true; }
注: FileInputStream 和 FileReader 都不支持标记
//标记 public void mark(int readAheadLimit) throws IOException { if (readAheadLimit < 0){ throw new IllegalArgumentException("Read-ahead limit < 0"); } synchronized (lock) { ensureOpen(); mark = next; } }
注: mark的使用并不相当于指针,需要和reset()方法一起使用 --> 和RandomAccessFile的seek操作不是一个性质
//重置指针 public void reset() throws IOException { synchronized (lock) { ensureOpen(); next = mark; } }
注: 将mark标记赋给next,reset()和mark()两个方法配合使用
//跳过流中指定数量的字符 返回跳过的字符数 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; } }
注: 正数往前跳,负数往后跳
3. 测试代码
//访问字符串 StringReader
import java.io.IOException;
import java.io.StringReader;
public class StringReader_work {
public static void StringReader() {
String str = "今天外面真的冷啊果然应该点外的";
try {
//1. 构造方法 传入字符串
StringReader stringReader = new StringReader(str);
//2. int read() 读操作,读取一个字符 (将String字符串操作 适配成 Reader字符操作 对外提供服务)
// int read=stringReader.read();
// System.out.println((char) read);
//int read(char cbuf[]) throws IOException 批量读
char[] chars = new char[3];
int read1=stringReader.read(chars);
System.out.println(new String(chars,0,3));
//int read(char cbuf[], int off, int len) 批量读
// char[] chars1 = new char[3];
// int read2=stringReader.read(chars1,0,3);
// System.out.println(new String(chars1,0,3));
// boolean ready() 判断数据源是否存在
stringReader.ready();
//3. markSupported() 是否支持标记 FileInputStream和FileReader 都不支持
System.out.println("是否支持标记:"+stringReader.markSupported());
// void mark(int readAheadLimit) throws IOException 标记
//TODO: 测试发现并未从标记位置读,依旧是接着原先next所指位置读数据
stringReader.mark(5);
char[] chars2=new char[3];
int read3 = stringReader.read(chars2,0,3);
System.out.println("mark标记后读三个数:"+new String(chars2,0,3));
//TODO:mark使用并不相当于指针 --> 和RandomAccessFile的seek操作不是一个性质
// void reset() throws IOException 重置指针
// 单独使用 reset() 方法
stringReader.reset();
char[] chars3=new char[3];
int read4 = stringReader.read(chars3,0,3);
System.out.println("单独使用reset()方法:"+new String(chars3,0,3));
// mark()方法 与 reset()方法 结合使用
stringReader.mark(2);
stringReader.reset();
char[] chars4=new char[3];
int read5 = stringReader.read(chars4,0,3);
System.out.println("mark()与reset()结合使用:"+new String(chars4,0,3));
// long skip(long ns) throws IOException 跳过流中指定数量的字符 返回跳过的字符数
stringReader.skip(2); //正数往前跳
// stringReader.skip(-2); //负数往后跳
char[] chars5=new char[3];
int read6 = stringReader.read(chars5,0,3);
System.out.println("向前跳两个字符:"+new String(chars5,0,3));
//关闭流
stringReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
StringReader();
}
}
运行结果
读取前三个字符:今天外 是否支持标记:true mark标记后读三个数:面真的 单独使用reset()方法:面真的 mark()与reset()结合使用:冷啊果 向前跳两个字符:该点外

浙公网安备 33010602011771号