2019年其他事情比较多,很多学习的记录都以纸质笔记的方式记录,博客也没有进行更新。今年将学习的东西继续总结记录,主要包括以下几个方面:Docker、数据库的分布式部署、Java基础、SpringMVC、Vue。继续将网页demo的功能完善。
之前每次遇到文件处理都会头疼,各种类型的输入流输出流分不清楚。这次好好梳理一下,各种流的定义及用法。
流的用处是什么?可以把程序想象成一个水池,两根水管接入这个水池。
字节流与字符流的区别在哪儿?由于JAVA的底层数据都是byte类型,每一字节是8位二进制,字节流是最基础的流,每次读取一个字节。但是这种流在传输字符的时候不方便,经过编码后,一个字符长度会超过一字节,比如说“李白”:
如果通过字节流来传输,每次都需要转码,会很麻烦,因此产生了字符流,减少了转码的步骤,使用起来更方便。顺便说一下可以看出UTF8比GBK更占空间。
一般来讲,输入流用于读取文件(包括InputStream),输出流用于写文件(OutputStream)。这两个流都是抽象类,有多个实现类。
以下的代码:
使用getClass.getResourceAsStream获取到一个文件字节输入流,然后用available方法获取长度估算。发现一个有意思的地方,就是in.available()得到的大小是107字节,是文件的大小,但是for循环打印出来的字节只有53个字节,这个比较奇怪。
以下几个都是InputStream的子类:
FileInputStream用来从文件中读取数据:
我们来试一试,发现available()方法获取的还是107字节,for循环打印出来106字节。
ByteArrayInputStream用来从字节数组中读取数据:
得到的长度是12,与之前计算是一样的,4个字符UTF8编码后共12字节。在网上查询之后,发现一个流的特性,即流无法重复读取,来测试一下。
得到的结果是12、11、10…0,说明数据流中可用的字节流在变少,并且在后面无法继续read,这个应该是IO流的一个通用特性,最后使用new String恢复了这个字符串。
输入字符流的抽象类是Reader,该类的子类必须要实现的方法是read() 和close(),在read()方法中,一般是向一个char数组写入读出的数据,在JAVA中,一般是不推荐使用char这个类型的。下面来看看Reader的子类有哪些:
使用String初始化了一个StringReader,然后把它打印出来,这里我发现字符流居然没有available()方法,判断是否可读需要看read()什么时候返回-1。测试了FileReader之后,发现功能也类似。
在查看网上的资料的时候,发现还有另外一种分类,根据IO流的功能,被分为节点流与处理流。节点流直接连接程序与数据源,而处理流必须和节点流一起,向节点流添加额外的功能。例如InputStream、OutPutStream、Reader、Writer都是节点流。
我觉得这个图很科学,处理流的工作需要依赖于节点流,就像管道外面套的保护层一样,可以根据不同的用途来进行替换。而处理流也分为三种,一种是缓冲流,一般带Duffered前缀。第二种是转换流,将数据流与字符流进行转换。第三种叫做数据流,一般带Data前缀。
来看一下字符缓冲流BufferedReader。它的功能是从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取。 BufferedReader的构造方法中,需要传入Reader,使用代码如下:
比起原有的节点流,多出了readLine()方法用于读取行、ready()方法用于判断是否可读,确实操作比字符流更方便。而缓冲字节流BufferedInputStream从方法上看不出有什么区别,从说明上是增加了缓冲输入和支持mark和reset方法,应该同样是提高了原版的操作性,这个以后有时间再看一下。
输入流的写入会依赖于底层平台,如果底层系统要求文件只能被打开一次,那么多个输入可能会抛出错误。看了前面几个,输出流与输入流只是方向不同而已,用法基本一致,其子类包括:
一般流用在文件的写入读取上比较多,这边来试试FileOutputStream。
检查目标路径的文件,已经有了,并且写入了编码后的数据。这里需要注意的是,每次write的时候,都是覆盖写入。如果需要接着之前的数据写,需要手动设置偏移量。
输出字符流的抽象类是Writer,其子类包括:
通过对FileWriter的测试,发现一个有意思的地方
上面的代码没办法将字符写入文件,一开始我以为是出什么问题了,后来才发现,字符流在写入之后,需要执行flush()方法将数据冲入目标文件,执行close()也会有同样的效果,并且输入流如果没关闭,可能也会引起一些其他问题。但是使用OutputStream却不需要。
总结一下,现在得到的信息有:
后面还有一些转换流的用法需要下来再看一下。