[疯狂Java]I/O:处理流、PrintStream简介、I/O体系、字符串作为流节点

1. 处理流PrintStream的简单使用:

    1) 处理流最大的特点就是对节点流的包装,因此只要构造器的参数是节点流的一定就是处理流(PrintStream、BufferedStream等),而构造器参数是节点本身的就是节点流(FileInputStream等);

    2) 处理流的两大好处:操作简单(对象方法使用很简单,基本源自各编程语言的模型,通用性强)、执行效率更高;

    3) PrintStream简介:

         i. System.out就是PrintStream,只不过底层包装的节点流是标准输出流(显示屏);

         ii. 虽然它是字节流,但是它可以方便输出字符,里面提供了print、println等方法;

!!print系列最强大的地方就是可以输出Java对象(前提是Java对象要实现串行化,否则就默认只能输出类的名字,以及对象哈希码);

         iii. 其输出字符的效率要比用PrintWriter输出字符的效率还要高(因为它处理直接就是二进制字节),而字符在处理的时候还要经过一层编解码环节;

         iv. 因此输出字符都应该优先考虑使用字节处理流!!

    4) 示例:使用PrintStream写文件

public class Test {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		try (
			FileOutputStream fis = new FileOutputStream("test");
			PrintStream ps = new PrintStream(fis)
		) {
			ps.println("lalala"); // 输出文本
			ps.println(new Test()); // 输出对象
		}
		catch (IOException e) {
			e.printStackTrace();
		}
	}

}
    5) 处理流关闭后底层包装的节点流会自动关闭(其实API中处理流的close就是直接调用包装的节点流的close方法的):void PrintStream.close();


2. Java的I/O体系:

    1) Java的I/O体系非常庞大,主要分为两大部分:

         i. java.io包下的标准I/O流:InputStream、Reader、OutputStream、Writer、ByteArrayInputStream、PrintStream、BufferedReader等等常见的

         ii. JDK其它包下的特殊I/O流:AudioInputStream、ZipInputStream等处理多媒体、加解密、压缩/解压的I/O流;

    2) 内容、类型繁多,光是标准I/O流就有40多种,这是因为Java为了实现更好的设计,按照I/O流的功能进行细分了;

    3) 虽然东西多,但是非常规律,就按照字节流、字符流分,而每种字节流和字符流又可以分为输入流和输出流,因此你真正需要记忆的大约就是(总数量÷4)那么多就行了,也就是10种作用,用的多了就记住了;


3. 以字符串作为流节点进行I/O:

    1) 前面介绍了,既然可以用数组(字节、字符)作为流节点,那么自然会想到用字符串作为流节点专门用来处理字符流;

    2) 其Java类是StringReader和StringBuffer,既然是专门处理字符的,因此就没有StringInputStream、StringOutputStream的版本了;

    3) 构造器:

         i. StringReader的构造器很正常,直接以一个String作为节点:StringReader(String s);

         ii. StringWriter的构造器不用传字符串,它内部自己维护这一个StringBuffer作为字符串节点:

public class StringWriter extends Writer {

    private StringBuffer buf;

    /**
     * Create a new string writer using the default initial string-buffer
     * size.
     */
    public StringWriter() {
        buf = new StringBuffer();
        lock = buf;
    }
...
...
!!由于String是不可变的,而输出流又是需要改变缓冲区内容的,因此输出流需要使用StringBuffer充当流节点(可变);

              a. 默认的无参构造器可以看到开辟的缓存空间是0,即从0开始增长;

              b. 有参构造器:

public StringWriter(int initialSize) {
    if (initialSize < 0) {
        throw new IllegalArgumentException("Negative buffer size");
    }
    buf = new StringBuffer(initialSize);
    lock = buf;
}
!!给定一个初始的缓存大小,后期超过了会自动增长;

!!那你可能会问,既然不能自己指定流节点StringBuffer,那有什么意义呢??我就是想查看输出后的结果,但是现在那个StringBuffer是StringWriter的内部成员,难道我还要隔着一层StringWriter来访问吗?

        a. StringWriter的toString其实就是返回其StringBbuffer中的字符串内容,因此是可以轻松访问到的;

        b. 那上面那个问题还是没有解决,那为什么不可以直接传入一个StringBuffer作为流节点呢?为什么一定要使用内部的StringBuffer呢?

        c. 答案其实很简单,Java就是把StringWriter设计成最最高级的StringBuffer,其实就是StringBuffer的强有力升级,StringBuffer对内容进行修改只能通过像什么setCharAt之类的传统方法,而这些方法在几乎所有编程语言中都有提供(类似的),但是StringWriter可以经过处理流包装(PrintWriter)使用更加高级、强大的方法来修改其中的字符,那不就变成了一个可以使用print、println之类的方法来修改字符的高级StringBuffer了吗??

    4) 示例:

public class Test {

	public static void main(String[] args) throws IOException {
		String src = "hello!\nOK\nGoodMorning!\n";
		
		char[] cbuf = new char[128];
		int hasRead = 0;
		try (StringReader sr = new StringReader(src)) {
			while ((hasRead = sr.read(cbuf)) > 0) {
				System.out.println(new String(cbuf, 0, hasRead));
			}
		}
		
		try (StringWriter sw = new StringWriter(20)) {
			sw.write("lalala\n");
			sw.write("goodgoodgood\n");
			System.out.println(sw); // 默认调用了toString方法
		}
	}
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值