本篇将要讲述的是java io包中的StringReader和StringWriter。这两个类都是Reader和Writer的装饰类,使它们拥有了对String类型数据进行操作的能力。

下面还是先附上源码,然后对其进行简单的分析:

StringReader:

package java.io;public class StringReader extends Reader {//内置了一个String类型的变量,用于存储读取的内容。因为Reader只需要读取无需对数据进行改变,所以此时一个String类型变量就已经足够了。private String str;//定义了3个int型变量,length表示读取的字符串数据的长度,next表示下一个要读取的位置,mark表示标记的位置。private int length;private int next = 0;private int mark = 0;/*** 一个带一个参数的构造方法,传入的参数是一个String类型数据,通过s初始化内置的str和length属性。*/public StringReader(String s) {this.str = s;this.length = s.length();}/** * 该方法用于判断当前流是否处于开启状态,本质就是检测内置的str是否被赋值。*/private void ensureOpen() throws IOException {if (str == null)throw new IOException("Stream closed");}/*** 每次读取一个字符的read方法,最终返回读取字符的int值。*/public int read() throws IOException {synchronized (lock) {//进行操作前,确保当前流处于开启状态。ensureOpen();//如果读取的位置,超过了数据的总长度,那么直接返回-1,表示已无数据可读。if (next >= length)return -1;//正常情况下通过next索引结合String类型的charAt方法,来从str中取出对应的字符数据。return str.charAt(next++);}}/*** 每次读入多个字符的read方法,最终返回实际读取的字符个数。该方法有3个参数,第一个参数为一个字符数组,用于存储读取的数据,第二和第三个参数为一个int* 变量,分别为开始在数组中存储数据的起点和存储数据的长度。*/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;//定义了一个int型值n,用来接收length-next和len之间的较小值,一般情况下使用len即可,如果len长度超过了数据的总长度,那么就使用length-next的值。int n = Math.min(length - next, len);//使用String类的getChars方法,将指定str从next到next+n位置的数据拷贝到传入cbuf中,拷贝位置从off开始。str.getChars(next, next + n, cbuf, off);//数据读取拷贝完毕后,将下一个读取的位置向后移位n位,最后返回n,即实际读取的数据长度。next += n;return n;}}/*** 该方法用于跳过指定长度的数据。*/public long skip(long ns) throws IOException {synchronized (lock) {//进行操作前先确定当前流是否处于开启状态。ensureOpen();//如果当前读取的位置已经位于读取数据的末尾或者已经超过了数据总长度,那么直接返回0,因为此时已经无法再跳过数据进行读取了。if (next >= length)return 0;//定义了一个long型数据n用来存放length-next和ns之间的较小值,一般情况下是ns起作用,如果ns超过了当前未读取的数据总长度,那么使用length-next。long n = Math.min(length - next, ns);//这里是为了处理传入的ns是负数的情况,当传入的值为负数时,此时读取位置应当向回移动,在上一布操作中如果传入的ns为负数的话,那么此时的n必定是ns//Math.max(-next,n)则保证了只有只有当读取位置大于回读的数量时才可以回读,所以最多之能回退到数据的起点位置。n = Math.max(-next, n);//下一次读取的位置移动n个位置,最终将n返回。next += n;return n;}}/*** 该方法用于判断当前流是否处于可读状态。*/public boolean ready() throws IOException {synchronized (lock) {ensureOpen();return true;}}/*** 该方法用于判断当前流是否支持流标记功能。*/public boolean markSupported() {return true;}/*** 该方法用于在指定位置留下流标记,与reset方法连用,可以试当前读取位置回退到在流中的标记位置*/public void mark(int readAheadLimit) throws IOException {//对传入的参数进行安全检测,标记的位置不能小于0,否则抛出相应的异常。if (readAheadLimit < 0){throw new IllegalArgumentException("Read-ahead limit < 0");}synchronized (lock) {//在进行操作前,确定当前流处于开启状态。ensureOpen();//使用mark变量记录下当前读取的位置。mark = next;}}/*** 该方法用于将当前读取位置回退到流中的标记位置。*/public void reset() throws IOException {synchronized (lock) {//在进行操作前,确定当前流是否处于开启状态。然后将当前读取位置回退到mark处。ensureOpen();next = mark;}}/*** close方法,关闭当前流,将内置的str指向null。*/public void close() {str = null;}
}

StringWriter:

package java.io;public class StringWriter extends Writer {//内置了一个StringBuffer,因为这里牵扯到了数据的改变,所以简单的String类型并不能满足我们。private StringBuffer buf;/*** 一个不带参的构造函数,内部为buf进行了初始化,并将该缓存区作为了内置锁对象。*/public StringWriter() {buf = new StringBuffer();lock = buf;}/*** 一个带一个参数的构造函数,传入的参数为一个int型值,该值决定了内置buf初始化时的容量大小。*/public StringWriter(int initialSize) {if (initialSize < 0) {throw new IllegalArgumentException("Negative buffer size");}buf = new StringBuffer(initialSize);lock = buf;}/*** 该方法用于流中每次写入一个字符。*/public void write(int c) {buf.append((char) c);}/*** 该方法用于向流中每次写入多个字节。*/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);}/*** 该方法每次向流中写入一个字符串类型的数据。*/public void write(String str) {buf.append(str);}/*** 该方法每次向流中写入一个字符串数据的一部分。*/public void write(String str, int off, int len)  {buf.append(str.substring(off, off + len));}/*** 该方法基本等同于上面的write(String str)方法,可以将制定的字符序列写入流中。*/public StringWriter append(CharSequence csq) {if (csq == null)write("null");elsewrite(csq.toString());return this;}/*** 可以将一个字符序列的一部分写入流中,最后返回流本身。*/public StringWriter append(CharSequence csq, int start, int end) {CharSequence cs = (csq == null ? "null" : csq);write(cs.subSequence(start, end).toString());return this;}/*** 可以将一个字符数据写入流中的,最后返回流本身。*/public StringWriter append(char c) {write(c);return this;}/*** 将内置缓存区中的数据装换为String类型并返回。*/public String toString() {return buf.toString();}/*** 返回内置的StringBuffer对象。*/public StringBuffer getBuffer() {return buf;}/*** 该方法本是将缓存中的数据强制写出,在本类是一个空实现。*/public void flush() {}/*** 该方法本市用于关闭流及释放流相关联的系统资源,在本类是一个空实现。*/public void close() throws IOException {}}

通过上面对源码的简单分析,我们队StringReader和StringWriter有了初步的认识,下面通过一个简单的小例子来展示其用法。

package StringIO;import java.io.StringReader;
import java.io.StringWriter;public class StringIOTest {public static void main(String[] args) {try (StringReader sr = new StringReader("just a test~");StringWriter sw = new StringWriter()) {int c = -1;while((c = sr.read()) != -1){sw.write(c);}//这里展示了即使关闭了StringWriter流,但仍然能获取到数据,因为其close方法是一个空实现。sw.close();System.out.println(sw.getBuffer().toString());} catch (Exception e) {e.printStackTrace();}}
}

刚开始我是比较奇怪这两个类为什么会存在的,因为这与直接使用String类来进行数据操作,后来在网上看到别人的解释,如果你遇到一个情景是你必须使用一个Reader或者Writer来作为参数传递参数,但你的数据源又仅仅是一个String类型数据,无需从文件中写出,那么此时就可以用到它们。并且值得注意的是StringWriter中,写入的数据只是存在于缓存中,并不会写入实质的存储介质之中。

以上为本篇内容。

java IO笔记(StringReader/StringWriter)相关推荐

  1. 学习韩顺平老师java io 笔记整理

    一.文件 文件流 文件在程序中以留的形式来操作的 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nXoI6Vnc-1642335857608)(F:\人生苦短,我用IO ...

  2. 【java学习笔记-io流 文件读写和键盘读写】带缓存的输入/输出流和数据输入/输出流

    文章目录 字节流类 带缓存的输入/输出流 BufferedReader与BufferedWriter类 下面的例子程序演示了read()方法,从控制台读取字符直到用户键入"q": ...

  3. java IO流(复习,上课笔记)

    IO流 流 流:代表任何有能力产出数据的数据源对象或者是有能力接受数据的接收端对象 流的本质:数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作 凡是与Java外部进行交互的,都叫做 ...

  4. java IO流-java学习笔记

    1:登录注册IO版本案例(掌握) 要求,对着写一遍. cn.itcast.pojo User cn.itcast.dao UserDao cn.itcast.dao.impl UserDaoImpl( ...

  5. Java学习笔记(7)——Java基础之IO多线程网络思维导图

    Java面向对象学习笔记之:包括IO(字节流,字符流,节点流,处理流).线程(线程创建,线程控制,线程同步).网络(TCP Scoket,  UDP Scoket)(全屏观看Java学习笔记(7)-- ...

  6. Java IO学习笔记总结

    Java IO学习笔记总结 前言 前面的八篇文章详细的讲述了Java IO的操作方法,文章列表如下 基本的文件操作 字符流和字节流的操作 InputStreamReader和OutputStreamW ...

  7. Java学习笔记--字符串和文件IO

    1.Java中的字符串类和字符的表示 2.区分String,StringBuilder和StringBuffer 3.从命令行中给main方法传递参数 4.文件操作 1 Java中的字符串和字符 1. ...

  8. java语言笔记io

    java语言笔记(进阶篇) 01-IO 1.基本类 2-IO-File(文件) File:文件和目录(文件夹)的路径 (1)IO基础 ①路径 package JAVAIO1; import java. ...

  9. IO流完整笔记,个人学习的手敲笔记,看完你就能学会Java IO流

    最近在准备面试,所以把之前的笔记都看了一遍,这是在学习IO流时做的笔记,觉得还是挺详细的,和大家分享一下.准备面试时间比较赶,我平时的笔记是在腾讯文档上中的,直接拷贝过来了,可能排版不太兼容,大家见谅 ...

最新文章

  1. 临危不乱,.Net+IIS环境经常出现的问题及排障。
  2. lhgdialog 4.2.0 正式版发布
  3. NYOJ 士兵杀敌(四) 树状数组
  4. Git常用命令使用大全
  5. Scala-2.13.0 安装及配置
  6. WPF(Windows Presentation Foundation)Overview
  7. 最大素数有用吗?安全上网就靠它
  8. CSS3 Flexbox 弹性布局
  9. Bailian4138 POJ NOI MATH-7827 质数的和与积【数论】
  10. 无心插柳,再次浅谈.net资源的回收
  11. Android菜鸟的成长笔记(23)——获取网络和SIM卡信息
  12. android 关闭jack_安卓编译 Jack server 错误问题解决办法
  13. MINIST数据集读取
  14. 基于python管理系统论文_基于Python的运动计费管理系统
  15. 如何在电脑上将PDF文件转换成word?
  16. numpy矩阵升维,拼接
  17. JS实现鼠标点击爱心绘制多边形每日一言功能
  18. C99 designator ‘name’ outside aggregate initializer
  19. 一阶的RC高低通电路和微积分电路有什么区别
  20. js中 数组的操作 push(),pop(),shift(),unshift() 简介

热门文章

  1. python stdout_详解使用python的logging模块在stdout输出的两种方法
  2. 如何让三维激光扫描外业工作变得轻松高效?
  3. PHP:2019年你面试会遇到的题目及解答(汇总)
  4. 一个常用的自定义弹框封装(适配 AndroidX),加载 ProgressDialog,状态显示的 StatusDialog 和自定义 Toast,全部支持背景颜色,圆角,边框和文字的自定义,构建者模
  5. 计算机分级就黑屏,酷大师常见问题之黑屏、崩溃,奉上正确解决方法
  6. js日期加减一天_Js日期加减(天数),时间加减,日期运算,可直接调用
  7. android 微信评论功能,安卓微信7.0.10正式版发布:没有朋友圈评论功能
  8. 4 英雄出场王(C++思路和代码)分治法练习4
  9. MySql添加索引的几种方式
  10. 学习笔记——RSA加密签名