Java StringReader流的使用
一、StringReader流定义
API说明:字符串输入流、其本质就是字符串
二、StringReader的实例域
//流对象
private String str;
//流的长度
private int length;
//流的当前位置,下个字符的索引
private int next = 0;
//流的标记位置
private int mark = 0;
三、StringReader流构造函数
public StringReader(String s) {
this.str = s;
this.length = s.length();
}
四、StringReader流的API
1)read()
:从流中读取单个字符,若到文件末尾则返回-1
public int read() throws IOException {
synchronized (lock) {
ensureOpen();
if (next >= length)
return -1;
return str.charAt(next++);
}
}
2)read(char cbuf[], int off, int len)
:读取最多len个字节到目标数组中,从目标数组的下标off开始存储,返回实际读取的字节数
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;
}
}
3)close()
:关闭流无效,关闭后调用该类其它方法会报异常
public void close() {
str = null;
}
五、StringReader流的作用
暂未使用故未知晓,故先了解功能
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. 基本方法
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;
}
}
标记相关方法
//判断是否支持标记
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()结合使用:冷啊果
向前跳两个字符:该点外
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。