IO(输入输出字符流)以及File类

2019-08-23  本文已影响0人  不小心丢了

字符流

InputStream类和OutputStream类在读写文件时操作的都是字节,如果希望程序中操作字符,使用这两个类就不太方便,为此JDK提供了字符流。同字节流一样,字符流也有两个抽象的顶级父类,分别是Reader和Writer,其中,Reader是字符输入流,用于从某个源设备读取字符。Writer是字符输出流,用于向某个目标设备写入字符。Reader和Writer作为字符流的顶级父类,也有许多子类。

字符流操作文件

程序开发中,经常需要对文本文件的内容进行读取,如果想从文件中直接读取字符,便可以使用字符输出流FileReader,通过此流可以从关联的文件中读取一个或一组字符。

首先在项目当前目录下新建文本文件“reader.txt”并在其中输入字符“itcast”,然后创建一个使用字符输入流FileReader读取文件中字符的类。

需要注意的是,字符输入流的read()方法返回的是int类型的值,如果想获得字符就需要进行强制类型转换,如上面代码第十行将变量ch转为char类型再打印。

如果向文件中写入字符就需要使用FileWriter类,该类是Writer的一个子类。

程序运行后会在当前目录下生成一个名称为“writer.txt”的文件,打开此文件会看到以下内容

FileWriter同OutputStream一样,如果指定的文件不存在,就会先创建文件,再写入数据,如果文件存在,首先会清空文件中的内容,再进行写入。如果想在文件末尾追加数据,同样需要调用重载的构造方法。

包装流可以通过对一个已存在的流进行包装来实现数据读写功能,利用包装流可以有效地提高读写数据的效率。字符流同样提供了带缓冲区的包装流,分别是BufferedReader和BufferedWriter,其中,BufferedReader用于对字符输入流进行包装,BufferedWriter用于对字符输出流进行包装。需要注意的是,在BufferedReader中有一个重要的方法readLine(),该方法用于一次读取一行文本。下面来学习如何使用这两个包装流实现文件的拷贝。

其中,readLine()方法会逐个读取字符当读到回车符'\r'或换行符'\n'时会将读到的字符作为一行的内容返回

需要注意的是。由于字符缓冲流内使用了缓冲区,在循环中调用了BufferedWriter的write()方法写入字符时,这些字符首先会被写入缓冲区,当缓冲区写满或调用close()方法时,缓冲区中的字符才会被写入目标文件。因此在循环结束时一定要调用close()方法,否则极有可能会导致部分存在缓冲区中的数据没有被写入目标文件。


转换流

前面的IO流可以分为字节流和字符流,有时字节流和字符流之间也需要进行转换。在JDK中提供了两个类可以将字节流转换为字符流,它们分别是InputStreamReader和OutputStraemWriter。

InputStreamWriter是Reader的子类,它可以将一个字节输入流装换成字符输入流,方便直接读取字符。OutputStreamWriter是Write的子类,它可以将一个字节输出流转换为字符输出流,方便直接写入字符。

实现了字节流和字符流之间的转换,将字节流转换为字符流,从而实现直接对字符的读写。需要注意的是,在使用转换流时只能针对操作文本文件的字节流进行转换如果字节流操作的是一张图片,此时转换为字符流就会造成数据丢失

File类

IO流可以对文件的内容进行读写操作,在应用程序中还会经常对文件本身进行一些常规操作,例如创建一个文件、删除或者重命名某个文件、判断硬盘上某个文件是否存在、查询文件最后修改时间等。针对文件的这类操作,JDK中提供了一个File类,该类封装了一个路径,并提供了一系列方法用于操作该路径所指向的文件。

File类用于封装一个路径,这个路径可以是从系统盘符开始的绝对路径,也可以是相对于当前目录而言的相对路径。File类内部封装的路径可以指向一个文件,也可以指向一个目录,在File类中提供了针对这些文件或目录的一些常规操作。具体可以自己查看API。

首先,在当前目录下创建一个文件“example001.txt”并在文件中输入内容“itcast”,然后创建一个使用File类常用方法的类,来查看文件的相应内容。

遍历目录下的文件

File类中String[ ] list() 列出指定目录的全部内容,只是列出名称

创建了一个File对象,并指定了一个路径,通过调用File的isDirectory()方法判断路径指向的是否为存在目录,如果存在就调用list()方法,获得一个String类型的数组names,数组中包含这个目录下所有文件的文件名。接着通过循环遍历数组names,依次打印出每个文件的文件名。

虽然上面实现遍历一个目录下所有文件的功能,然而有时程序只是需要得到指定类型的文件,如获取指定目录下所有的“.java”文件。针对这种需求,File类中提供了一个重载的list(FilenameFilter filter)方法,该方法接收一个FilenameFilter类型的参数。FilenameFilter是一个接口,被称为文件过滤器,当中定义了一个抽象方法accept(File dir,String name)。在调用list()方法时,需要实现文件过滤器FilenameFilter,并在accept()方法中做出判断,从而获得指定类型的文件。

步骤分析list(FilenameFilter filter)方法的工作原理
①调用list()方法传入FilenameFilter文件过滤器对象
②取出当前File对象所代表目录下的所有子目录和文件
③对于每一个子目录或文件,都会调用文件过滤器对象的accept(File dir,String name)方法,并把代表当前目录的File对象以及这个子目录或文件的名字作为参数dir和name传递给方法
④如果accept()方法返回true,就将当前遍历的这个子目录或文件添加到数组中,如果返回false,则不添加。

接下来通过一个案例来演示如何遍历指定目录下所有扩展名为“.txt”的文件。

有时候在一个目录下,除了文件,还有子目录,如果想得到所有子目录下的File类型对象,list()方法显然不能满足要求,这时就需要使用File类提供的另一个方法listFiles()。listFiles()方法返回一个对象数组,当对数组中的元素进行遍历时,如果元素中还有子目录需要遍历,则需要使用递归。

定义了一个静态方法fileDir(),该方法接收一个表示目录的File对象。在方法中,首先通过调用listFiles()方法把该目录下所有的子目录和文件存到File类型的数组files中,接着遍历数组files,并对当前遍历的File对象进行解析。如果是目录就重新调用fileDir()方法进行递归,如果是文件就直接打印输出文件的路径,这样该目录下的所有文件就被重新遍历出来了。

删除文件及目录

首先在D盘中创建一个名称为test的文件夹,然后在文件夹中创建一个文本文件,接下来创建一个使用delete()方法删除文件夹的类。

File类的delete()方法只能删除一个指定的文件,加入File对象代表目录,并且目录下包含子目录或文件,则File类的delete()方法不允许对这个目录进行直接删除。这种情况下,需要通过递归的方法将整个目录以及其中的文件全部删除。

上一篇下一篇

猜你喜欢

热点阅读