本文是IO类学习时的相关笔记,记录了一些学习时的实例和知识点。
IO类的含义
I:in
O:out
File类:文件和目录路径名的抽象表示
一参构造方法
创建格式
两参构造方法
第一个参数可以是之前创建的文件夹文件,也可以是路径,表示在指定的文件夹创建文件。
相应的可以使用对象.delete()进行删除。
其他常用方法:
String类型 getAbsolutePath()
获取文件的路径
String类型 getName()
获取文件名称
String类型 getParent()
获取父文件夹的名称
File类型 getParent()
获取父文件夹对象
String类型 getPath()
获取路径
long类型 length()
获取文件长度(大小)
boolean类型 exists()
判断是否存在
boolean类型 isDirectory()
判断是否是文件夹
boolean类型 isFile()
判断是否是文件
String[]类型 list()
获取文件夹里所有文件路径的目录
File[]类型 listFiles()
获取文件夹里所有的文件
boolean类型 mkdir()
创建文件夹
boolean类型 mkdirs()
创建文件夹并创建任何不存在的父文件夹
boolean类型 renameTo(目标)
重命名文件
重命名并且移动的操作。
值得注意的是,Java是一门跨平台语言,在不同操作系统下的路径分隔符和名称分隔符不同,这时候需要将原本操作系统下的分隔符使用pathSeparator和separator代替。
文件遍历案例:
先使用构造方法创建一个路径为E盘的文件对象e,调用listFiles()方法对e进行遍历操作,获得一个File类型的数组files。
这段语句的意思为对于路径e:\,获得该路径下一级所有文件,并存放在files这个数组中。
这里写了一个listFiles方法,参数是经过listFiles遍历之后e:\目录里所有的文件组成的数组files,上面的e.listFiles()是File类的方法,而listFiles()是我们自己声明的方法,不要弄混。
在方法中,先判断这个files数组是否为空,并且数组长度需要大于0,随后再进一步判断使用对象.isFile()方法判断该文件是否是文件,如果不是文件这说明是文件夹,再次新建一个File[]数组,重新调用方法进行递归。如果是文件说明这是我们需要进行判断的文件,先使用对象.getName()获得名字,同时使用对象.endWith(参数)方法判断是否是.avi型的文件。如果是则进行大小的判断,需要使用对象.length()方法,其中1024*1024指的是MB。
文件过滤器:
按照惯例先new一个e对象,路径为e:\ ,E盘根目录,这个文件直接调用方法listFiles(),
这个方法在下方进行解释。
声明方法,创建一个过滤器
先写过滤器,声明过滤规则,这是FileFilter接口的一个实现类,内容需要我们自己实现,这里的意思是传入的文件路径(这里是E盘),如果这个文件路径以.avi结尾,或者这个文件是文件夹则返回true,否则返回false。
这样一来过滤规则就完成了。
回到一开始创建的listFiles方法,先调用过滤器,new一个filter对象,传入的参数file文件调用过滤器方法,将过滤过的方法传入File[]数组,此时能传入的数组一定是在过滤器中为true的,即一定是文件夹或是以.avi为结尾的。
这里在开始遍历之前还需要进行数组非空和长度大于0的判断,否则会出现空指针异常。
开始遍历之后进行判断,如果是文件夹,则递归,如果不是,这里肯定是.avi结尾的文件,则直接打印。
对于以上的操作,过滤器部分还可以进行额外的优化。
使用匿名内部类,直接在方法中进行重写。
再进一步,由于是重写了方法,重写的FileFilter()方法new出filter对象,而filter对象又是在下方的file.listFiles()方法中直接调用,所以可以将此匿名内部类直接放入listFile()方法里。
这样写虽然对于不熟悉代码的初学者会不容易理解,但是随着熟练度提升应该掌握。
相对路径和绝对路径:
绝对路径:从盘符开始,是一个完整的路径。
例如:c:\a.txt
相对路径:在Java代码中是相对于项目目录的路径,这是一个不完整的便捷路径,在Java开发中很常用。
例如a.txt
这个相对路径是存在于项目文件夹中。
例子:
对于file2,new的路径是a.txt,使用file2.getAbsolutePath()获得绝对路径,可以看到a.txt这个文件存在了Demo项目文件夹里。
流概述:
字节流:
OutputStream:表示输出字节流的所有类的超类。
方法:
close()
关闭输出。
flush()
刷新此输出流并强制写出任何缓冲的输出字节。
有些输出会先进行缓存,再一次性输出,可以提高效率。
write() 写入有三个方法。
一个是write(byte[] b)
,可以写出某字节数组的所有内容。
write(byte[] b, int off, int len)
这个意思是在此字节数组中,从某个下标off开始写出多少个字节。
FileOutputStream:
OutputStream的一个子类,是实体类。文件输出流。
每一个FileOutputStream类的对象,都可以看做是向某个文件输出的流管道。我们可以通过这个对象向某个指定的文件输出内容。
构造方法:有四个主要使用的,可以分为两类
FileOutputStream(File file)//输入一个对象文件作为输出流目标
FileOutputStream(File file, boolean append)//输入一个对象文件,boolean为true的话则接着之前的文件写,false/不传则覆盖
FileOutputStream(String name)//输入一个文件路径作为输出流目标。
FileOutputStream(String name, boolean append)//输入一个文件路径,boolean为true的话则接着之前的文件写,false/不传则覆盖
实例:
InputStream:
主要方法:
close() 关闭
read() 从流中读取一个字节数据,每次读一个,如果超过长度就会读-1.
read(byte[] b) 从字节流读取一些字节数并且储存在缓冲数组b
子类:FileInputStream
构造方法:
FileInputStream(File file)//打开与实际文件的连接来创建文件输入流,
FileInputStream(String name)//通过路径来打开文件创建连接。
三个重要的方法:
与父类一致。
read()
方法的实例
read(byte[] b)
方法实例
一次读取一组数据 读到最后会返回-1。
在平常使用时尽量使用一次读取一组的操作,可以减少调用IO的频率,让程序读取数量大的时候不那么卡,一次一组的读取方式会更快。
文件加密和解密工具:
实例:
核心是对read读取的每一个字节进行^运算
字节流读取文字:
字符流会读取的时候出现乱码,因为一次读取长度可能不足以转化为一个字符。
![](https://img-blog.csdnimg.cn/20200905101151281.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0FyY2hpbW9udGFv,size_16,color_FFFFFF,t_70#pic_center)
字符输出:
字符流输出可以以字符为单位进行输出。
Class Writer类,Object的子类
主要方法:
close()
append(char c)
write(char[] cbuf)
write(int c)
write(String str)
FileWriter类,Write的子类
主要构造方法:
FileWriter(File file)//和FileOutputStream类似,对File对象file创建字符输出
FileWriter(File file,boolean append)//对File对象file,true则添加字符,false/无则覆写。
实例:
这里有个比较有意思的用法append() 追加方法。
append方法的源码返回的是this,意味着返回的是调用方法的当前对象。
那么fw.append(“汗滴禾下土”)返回的还是一个fw对象,此时可以对于返回的fw对象再次调用append()方法,这样就可以实现多次追加的效果。
字符读取(输入流):
Class Reader类,Object的子类
主要方法:
close() //关闭
read() //读取一个字符
read(char[] cbuf) //读取一串字符
read(char[] cbuf, int off, int len) //读取cbuf中从off下标开始的len个字符
实例
read()
read(char[] cbuf)
这里可以看到如果直接输出100个字符,在字符之后会有大量空格。
如果想要解决这个问题,我们可以利用read(char[] cbuf)方法的int类型返回值来操作,返回的int是数组的长度。此时我们赋值一个int len = fr.read(chars),这里的len就是数组的长度。读取出来的对象text在构造时从0下标开始,读取chars数组的len长度的字符,就是完整的数组了。
flush刷新管道:
在数据读写的时候有一个缓存区域,在进行读写操作时如果不调用flush的刷新操作,数据会在缓存区域保留,不写入文件。close()方法自带刷新的功能。所以在写入之后应该进行flush的刷新操作。
字节转换字符流:
字节流 “装饰”为字符流:使用了装饰者设计模式。
将输入的字节流装饰为字符流,使用InputStreamReader构造方法,参数中需要获取字节输入流,gkb是编码格式,最后正确读取。
在和客户端之类的进行交互的时候同理也可以使用字节流装饰为字符流,再用字符流进行输出的操作。
Print与BufferedReader:
print其实是字符输出流。
通过源码可以查看到是属于OutputStream的子类。其实System.out就是字符的打印流。
同理可以自己定义打印方法,向不同位置进行输出
在需要进行字符输出时可以使用打印流进行输出。
BufferedReader方法提供了一个缓存读取流,可以在读取时实现一次只读取一行。当读到末尾时会返回null。
收集异常日志:
在程序运行出现错误时,可以通过打印流将异常输出到一个txt文件中作为异常日志。
可以打印时间来进行时间记录。
properties类:
是一个Map集合。可以用来实现将键值对输出到文件中。
有两个主要方法:
load()
store()
实例:
此方法可以将程序中的MAP集合输出打印到文件中。
相应的可以读取MAP集合的文件打印出来。