存储&读取数据的方案
File简介
- File是java.io.包下的类,File类的对象,用于代表当前操作系统的文件(可以是文件或文件夹)
- 注意:File类只能对文件本身进行操作,不能读写文件里面存储的数据。
IO流简介
- 用于读写数据的(可以读写文件或网络中的数据...)
File
-
File类的对象可以代表文件/文件夹,并可以调用其提供的方法对象文件进行操作
-
创建File类的对象
-
注意:
-
File对象既可以代表文件,也可以代表文件夹。
-
File封装的对象仅仅是一个路径名,这个路径可以是存在的,也允许是不存在的
-
相对路径是不带盘符的,默认是到IDEA工程(必须确保是工程)下直接寻找文件的。一般用来找工程下的项目文件的项目文件
-
-
File类创建文件的功能
-
File类删除文件的功能
- 注意:delete方法默认只能删除文件和空文件夹,删除后的文件不会进入回收站
-
File类提供的遍历文件夹的功能
- 使用listFile方法时的注意事项:
- 当主调是文件或者路径不存在时,返回null
- 当主调是空文件夹时,返回一个长度为0的数组
- 当主调十一个有内容的文件夹时,将里面所有一级文件和文件夹的路径放在File数组中返回
- 当主调是一个文件夹,且里面有隐藏文件时,将里面所有文件和文件夹的路径放在File数组中返回,包含隐藏文件
- 当主调是一个文件夹,但是没有权限访问该文件夹时,返回null
- 使用listFile方法时的注意事项:
-
获取文件对象的绝对路径
递归
-
递归是一种算法,在程序设计语言中广泛应用
-
从形式上说,方法调用自身的形式称呼为方法递归(recursion)
-
递归可能出现死循环,导致、栈内存溢出
文件搜索
-
示例
字符集
标准ASCII字符集
- ASCII:美国信息交换标准代码,包括了英文、符号等
- 标准ASCII使用1个字节存储一个字符,首位是0,因此,总共可表示128个字符,对美国来说完全够用
GBK(汉字内码扩展规范,国标)
- 汉字编码字符集,包含了2万多个汉字等字符,GBK中一个中文字符编码成两个字节的形式存储。
- 注意:GBK兼容了ASCII字符集。
- GBK规定:汉字的第一个字节的第一位必须是1。所以读到1就读两个字节表示汉字,读到0就读一个字节的ASCII码
Unicode字符集(统一码,也叫万国码)
-
Unicode是国际组织制定的,可以容纳世界上所有文字、符号的字符集
-
UTF-32:四个字节表示一个字符
- 缺点:奢侈,占存储空间大,通信效率变低
-
UTF-8:
-
是Unicode字符集的一种编码方案,采取可变长编码方案,分四个长度区:1个字节,2个字节,3个字节,4个字节
-
英文字符、数字等只占1个字符(兼容ASCII编码),汉字字符占用3个字节。
-
-
-
注意:程序员在开发中应该使用UTF-8!
使用程序对字符进行编码和解码操作
-
对字符编码
-
对字符解码
-
编码器和解码器不同时会乱码,但英文和数字一般不会乱码,因为都兼容ASCII
IO流
-
IO流的分类
-
IO流的体系
字节流
FileInputStream(文件字节输入流)
-
作用:以内存为基准,可以把磁盘文件中的数据以字节的形式读入到内存中去
-
示例:
-
每次读一个字节
-
每次读多个字节
-
-
结论:
-
使用FileInputStream每次读取一个字节,读取性能较差,并且读取汉字输出会乱码
-
使用FileInputStream每次读取多个字节,读取性能得到了提升,但读取汉字输出还是会乱码
-
使用字节流读取中文,如何保证输出不乱吗,如何解决?
-
定义一个与文件一样大的字节数组,一次性读取完全部字节文件
-
官方为FileInputStream提供了如下方法,可以直接把文件的全部字节读取到一个字节数组返回
-
示例
-
-
直接把文件数据全部读取到一个字节数组可以避免乱码,是否存在问题?
- 如果文件过大,创建的字节数组也会过大,可能引起内存溢出
-
FileOutputStream(文件字节输出流)
-
作用:以内存为基准,把内存中的数据以字节的形式写出到文件中去
-
字节输出流写数据的方法
- len这个参数的单位是字节,中文在utf8中是3个字节
-
字节输出流如何实现写出去的数据可以换行?
os.write("\r\n".getBytes()); // \r是为了在win之外的系统也可以换行,两个写一起兼容性更好
-
用完管道要用
.close()
把管道关掉 -
示例
文件复制
-
示例
-
字节流非常适合做文件的复制操作
- 任何文件的底层都是字节,,字节流做复制时一字不漏的转移完全部字节,指导赋值后的文件格式一致就没问题
-
注意:复制的目标文件必须写名字,因为该操作无法自动生成一个文件
资源释放的方案
-
try-catch-finally
-
finally代码区的特点:无论try中的程序是正常执行了还是出现了异常,最后都一定会执行finally区,除非JVM终止
-
作用:一般用于在程序执行完后新型资源的释放操作(专业级做法)
-
ctrl+alt+t可以创建try-catch-finally
-
在try中定义管道变量的话,在finally块中检测不到这个变量,但在try之前创建又会异常报错,所以应该在外面创建空变量,在try中new出来
-
finally中程序会担心是否变量已经被释放了从而再次异常报错,这时候就需要在finally中再try、catch异常
-
这种方法使用起来代码十分臃肿
-
-
try-with-resource
-
jdk7开始,为了解决try-catch-finally中,finally解决方法代码臃肿,且finally中时常有其他结束操作的问题。
-
提供了更简单的资源释放方案try-with-resource
-
在try后括号中定义资源,该资源使用完毕后,会自动调用其close()方法,完成对资源的释放
-
示例
-
注意:try后的括号里只能放资源对象,不能定义一个变量
-
什么是资源?
-
资源一般指的是最终实现了AutoCloseable接口
-
-
-
字符流
FileReader文件字符输入流
-
作用:以内存为基准,可以把文件中的数据以字符的形式读入到内存中去
-
示例
FileWriter文件字符输出流
-
作用:以内存为基准,把内存中的数据以字符的形式写出到文件中去
-
字符输出流的注意事项
-
字符输出流写出数据后,必须刷新流,或者关闭流,写出去的数据才能生效
-
为什么要刷新?
- 不刷新的话IO调用次数过多,所以就先把内存缓冲区写完之后再同步一次IO,这样IO次数就变少了
-
如果不刷新缓冲区,直接结束程序,那数据可能不会存到文件中
-
刷新后,流可以继续使用
-
关闭方法包含刷新,但关闭后就无法继续使用
-
利用jdk7的特性,在try后的括号中new出的流会在try结束后自动调用关闭方法,所以使用这个特性后就不需要主动的关闭流!!!
-
缓冲流
- 缓冲流是改进了普通流,提高了普通流的性能
BufferedInputStream/BufferedOutputStream缓冲字节输入/输出流
-
缓冲字节输入/输出流默认有8kB的缓冲池,减少了传输次数
BufferedReader缓冲字符输入流
-
作用:自带8K(8192个)的字符缓冲池,可以提高字符输入流读取字符数据的性能
-
字符缓冲输入流新增的功能:按照行读取字符
- 这里想用readLine方法的话就不用多态写法了,因为这是BufferedReader独有的
-
示例:
BufferedWriter缓冲字符输出流
-
作用:自带8K的字符缓冲池,可以提高字符输出流写字符数据的性能
-
字符缓冲输出流新增的功能:换行
性能分析
原始流、缓冲流的性能分析
- 背景:使用四种流复制一个大文件
- 低级字节流:按照一个一个字节的形式复制文件
- 非常慢,简直让人无法忍受,直接淘汰,禁止使用
- 低级字节流:按照字节数组的形式复制文件
- 是比较慢的,但还可以接收
- 高级的缓冲字节流:按照一个一个字节的形式复制文件
- 虽然是高级管道,但一个一个字节的复制还是太慢了,无法忍受,直接淘汰
- 高级的缓冲字节流:按照字节数组的形式复制文件
- 非常快,推荐使用
- 低级字节流:按照一个一个字节的形式复制文件
- 低级管道只要把桶加大(例如把字符数组加大),性能也能变得好,所以低级流不一定就比高级流性能差
其他流
InputStreamReader字符输入转换流
- 解决不同编码时,字符流读取文本内容乱码问题
- 解决思路:先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流中的字符就不乱码了
- 背景:不同编码读取乱码问题
- 例如UTF-8的代码编码,读取GBK文件时出现乱码
- 示例
打印流
PrintStream/PrintWriter(打印流)
-
作用:打印流可以实现更方便、更高效的打印数据出去,能实现打印啥出去就是啥出去(比如97就会打印出97,而不会转为char中的'a')
特殊数据流
DataOutputStream(数据输出流)
-
允许把数据和其类型一并写出去
-
写进去很多时候看起来是乱码,但这个一般不是给人看的,而是给别人读取用的
DataInputStream(数据输入流)
-
用于读取数据输出流写出去的数据
-
读取的时候要和写入时的类型顺序一致,怎么发就怎么收
IO框架
-
什么是框架?
- 框架(Framework)是一个预先写好的代码库或一组工具,旨在简化和加速开发过程
- 框架的形式:一般把类、接口等编译成class形式,再压缩成一个.jar结尾的文件发行出去
-
什么是IO框架?
- 分装了Java提供的对文件、数据进行操作的代码,对外提供了更简单的方式来对文件进行操作、对数据进行读写等
-
步骤:
-
Commons-io框架
-
是apache开源基金组织提供的一组有关IO操作的小框架,目的是提高IO流的开发效率
-
示例
下面一行是java提供的
-
删除操作不考虑是否非空,调用会直接删除,谨慎使用!
-