第十三章、IO流_File类与递归/基本流/增强流/属性集与打印流__黑马Java第57期个人学习笔记_个人笔记

第一节、File类与递归

一、File类

(一)概念:

1、File类是文件和目录路径名的抽象表示,主要用于文件和目录的创建、查找和删除等操作。(也重写了toString为getPath)

2、绝对路径和相对路径:

(1)绝对路径 :从盘符开始的,全路径。

(2)相对路径 :相对于项目目录的路径。(开发常用)

(3)两个\\代表一个普通\(转义字符了解)

(二)方法

1、构造方法

(1)File(String pathname) :通过 将给定的路径名字符串转换为抽象路径名来 创建新的 File实例。 

(2)File(String parent, String child) :从 父路径名字符串 和 子路径名字符串 创建新的 File实例。

(3)File(File parent, String child) :从 父抽象路径名 和 子路径名字符串 创建新的 File实例。

2、常用方法

(1)获取gl((g*3,l*1)getAbsolutePath、getPath、getName、length)

①String getAbsolutePath():返回 此File的绝对路径名的字符串。

②String getPath() :返回 此File转换为路径名的字符串。 (toString方法调用此)

③String getName() :返回 此File表示的文件或目录的名称。 

④long length() :返回 此File表示的文件的长度。

(2)判断ei((e*1,i*2)exists,isDirectory,isFile)

①boolean exists() :判断 File表示的文件或目录是否实际存在。

②boolean isDirectory() :判断 File表示的是否为目录。

③boolean isFile() :判断 File表示的是否为文件。

(3)创删cmd(createNewFile, mkdir/mkdirs,delete)

①boolean createNewFile() :创建 新的空文件。

②boolean mkdir/mkdirs() :创建 此File表示的 空目录/父子目录。

③boolean delete() :删除 此File表示的 文件或目录。

!!!看类型,别被名字忽悠了!!!

(4)遍历l((l*2)list,listFiles)

①String[] list() :返回一个String数组,表示该File里的所有子文件或目录。

②File[] listFiles() :返回一个File数组,表示该File里的所有子文件或目录。 

(5)静态方法

①static String pathSeparator() :返回(与系统有关的)路径分隔符

static char pathSeparatorChar() :与系统有关的路径分隔符

源码:

②static String separator() :与系统有关的默认名称分隔符

static char separatorChar() : 与系统有关的默认名称分隔符

③操作路径:路径不能写死了

C:\develop\a\a.txt       Windows

C:/develop/a/a.txt       Linux

④用”+File.separator+”代表 \ or /

“C:”+File.separator+”develop”+File.separator+”a”+File.separator+”a.txt”

 

二、递归

(一)概念:

1、递归:指在当前方法内调用自己的这种现象。

2、递归分类(直接、间接)

①直接递归:方法自身调用自己。

②间接递归:A方法调用B方法,B方法调用C方法,C方法调用A方法。

(二)特点递归注意:

1、递归一定要有限定条件,保证递归的停止,并且递归次数不能太多,否则会栈内存溢出。

2、构造方法禁止递归。

(三)常用用法

1、递归累加求和:计算1~n的和

分析:num的累和 = num + (num-1)的累和,所以可以把累和的操作定义成一个方法,递归调用。

2、递归求阶乘:计算1~n的积

分析:推理得出:n! = n*(n-1)!

3、递归打印多级目录:

分析:多级目录的打印,就是目录的嵌套。遍历之前,不知有多少级目录,使用递归实现。

 

三、综合案例-结合Lambda表达式来看

(一)题目文件搜索

1、题目:搜索 D:\aaa 目录中的 .java 文件。

2、分析:

(1)目录搜索,无法判断多少级目录,所以使用递归,遍历所有目录。

(2)遍历目录时,获取的子文件,通过文件名称,判断是否符合条件。

(二)File过滤器(FileFilter、FileNameFilter)

1、概念

java.io.FileFilter是一个接口(唯一方法accept),是File的过滤器。该接口的对象可以传递给File类的listFiles(FileFilter)。

2、方法(唯一)

boolean accept(File pathname) :判断pathname是否包含在File目录中。

3、特点

(1)FileFilter接口作为参数,需要传递子类对象,重写其中方法。【匿名内部类】 or 【Lambda】。

(2)accept方法,参数为File,表示当前File下所有的子文件和子目录。保留住则返回true。

(此题目保留规则:①要么是.java文件。②要么是目录,用于继续遍历。)

(3)通过过滤器的作用, listFiles(FileFilter)返回的数组元素中,子文件对象都是符合条件的,可以直接打印。

4、匿名内部类代码

5、Lambda代码:

FileFilter是只有一个方法的接口,因此可以用lambda表达式简写。

 

第二节、IO基本流(字节流fisfos、字符流frfw)

一、IO概述

(一)概念

1、数据的传输,可以看做是一种数据的流动,按照流动方向,以内存为基准,分为`输入input` 和`输出output`,即流向内存是输入流,流出内存的输出流。

2、Java中I/O操作主要是指使用`java.io`包下的内容,进行输入、输出操作。输入即读取数据,输出即写出数据。

3、\r\n写出换行         (String str=”\r\n”;)

(二)IO分类

1、根据数据流向 :输入流、输出流

输入流(其他->内存) :把数据从 其他设备 读取到 内存 的流。

输出流(内存->其他) :把数据从 内存 写出到 其他设备 的流。

2、根据数据类型 :字节流、字符流

字节流 :字节为单位,读写数据的流。

字符流 :字符为单位,读写数据的流。

3、IO的流向与四大父类

(三)IO异常的处理try-with-resource

1、JDK7之前:try-catch-finally

2、JDK7之时:try-with-resource

该语句确保了每个资源在语句结束时关闭。(所谓的资源(resource)是指在程序完成后,必须关闭的对象。)

格式:

try (创建流对象语句,如果多个,使用';'隔开) {

    // 读写数据

} catch (IOException e) {

    e.printStackTrace();

}

3、JDK9改进:t-w-r引入对象简洁化

JDK9中try-with-resource的改进,对于【引入对象】的方式,支持的更加简洁。被引入的对象,同样可以自动关闭,无需手动close

格式对比:

 

二、字节流(fis、fos)

(一)fis字节输入流

1、InputStream(父类)常用方法:close、read*2

(1)close() :关闭此输入流并释放与此流相关联的任何系统资源。   

(2)int read() :从输入流读取一个字节,返回提升为int类型的值(末返-1)。

(3)int read(byte[] b) :从输入流中读取一个字节数组并保存,返回有效个数(末返-1)。

2、FileInputStream(子类)

(1)构造方法:

①FileInputStream(File file) :File对象 构造FileInputStream。

②FileInputStream(String name) :路径名 构造FileInputStream。 

(当创建一个流对象时,必须传入一个文件路径。该路径下,如果没有该文件,会抛出FileNotFoundException)

(2)常用方法:读取字节数据 read*2(字节读取、字节数组读取)

①字节读取:int read()方法,每次读一个字节,提升为int类型并返回,末返-1

②字节数组读取:int read(byte[] b),每次读b长度字节数组并保存于b,返回读取的有效字节个数,末返-1

(二)fos字节输出流

1、OutputStream(父类)常用方法:close、flush、write*3

(1)close() :关闭此输出流并释放与此流相关联的任何系统资源。

(2)flush() :刷新此输出流并强制任何缓冲的输出字节被写出。

(3)write*3:::(字节*1,字节数组*2)

①write(int b) :指定字节,输出到此输出流。

②write(byte[] b) :指定字节数组,输出到此输出流。

③write(byte[] b, int off, int len) :指定字节数组某部分,偏移量 off开始索引,len长度,输出到此输出流。

2、FileOutputStream(子类):

(1)构造方法:

①FileOutputStream(File file) : File对象 构造FileInputStream

②FileOutputStream(String name) : 路径名 构造FileInputStream

③FileOutputStream(File file, boolean append) : File对象 构造FileInputStream(T追加、F清空)

④FileOutputStream(String name, boolean append) : 路径名 构造FileInputStream(T追加、F清空)

(追加续写:保留目标文件中数据,继续添加新数据,t追f清)

此两个构造方法,参数中都需传入一个boolean类型的值,true追加数据,false清空原有数据。

(2)常用方法:写出字节数据 write*3(字节写出*1、字节数组写出*2)

①字节写出:write(int b),指定字节,输出到此输出流(即一次一个)。

②字节数组写出:

write(byte[] b),指定字节数组,输出到此输出流。

write(byte[] b, int off, int len),指定字节数组某部分,偏移量 off开始索引,len长度,输出到此输出流。

(三)字节流练习-图片复制

复制原理 :

 

三、字符流(fr、fw)

(一)fr字符输入流

1、Reader(父类)常用方法:close、read*2

(1)close() :关闭此流并释放与此流相关联的任何系统资源。   

(2)int read() : 从输入流读取一个字符,返回提升为int类型的值(末返-1)。

(3)int read(char[] c) :从输入流中读取一个字符数组并保存,返回有效个数(末返-1)。

2、FileReader(子类):构造用系统默认字符编码和默认字节缓冲区。

(1)构造方法:

①FileReader(File file) :File对象 构造FileReader。

②FileReader(String fileName) :路径名 构造FileReader。

(当你创建一个流对象时,必须传入一个文件路径。类似于FileInputStream。该路径下,如果没有该文件,会抛出FileNotFoundException)

(2)常用方法:读取字符数据 两种read(字符读取、字符数组读取)

①字符读取:int read()方法,每次读一个字符,提升为int类型并返回,末返-1

②字符数组读取:int read(char[] cbuf),每次读c的长度字符数组并保存于c,返回读取的有效字符个数,末返-1

(二)fw字符输出流

1、Writer(父类)常用方法:close、flush、write*5

(1)close():关闭此流,但要先刷新它。(与FOS不同:不关则写的缓冲区,没到文件)

(2)flush():刷新该流的缓冲。 

(3)write*5:::(字符*1,字符数组*2,字符串*2)

①write(int c):指定字符,输出到此输出流。

②write(char[] cbuf):指定字符数组,输出到此输出流。

③write(char[] cbuf, int off,int len):指定字符数组某部分,偏移量 off开始索引,len长度,输出到此输出流。

④write(String str):指定字符串,输出到此输出流。

⑤write(String str,int off,int len):指定字符串某部分,偏移量 off开始索引,len长度,输出到此输出流。

2、FileWriter(子类):构造用系统默认字符编码和默认字节缓冲区。

(1)构造方法

①FileWriter(File file):File对象 构造FileWriter

②FileWriter(String fileName):路径名 构造FileWriter

(当创一个流对象时,必须传入一个文件路径,类似于FileOutputStream。)

(2)常用方法:写出字符数据 write*5(字符写出*1、字符数组写出*2、字符串写出*2)

①字符写出:write(int b),指定字符,输出到此输出流(即一次一个)。

②字符数组写出:

write(char[] cbuf),指定字符数组,输出到此输出流。

write(char[] cbuf, int off, int len),指定字符数组某部分,偏移量 off开始索引,len长度,输出到此输出流。

③字符串写出:

write(String str),指定字符串,输出到此输出流。

write(String str, int off, int len),指定字符串某部分,偏移量 off开始索引,len长度,输出到此输出流。

(3)刷新关闭:缓冲区cbuf问题

因为内置缓冲区,如果不关闭输出流,无法写出字符到文件中;但如果关闭流对象,无法继续写出数据。

因此写出数据并继续使用流,需flush方法。

①flush:刷新缓冲区,流对象可以继续使用。

②close:先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。

 

 

第三节、增强流(缓冲流、转换流、序列流)

一、缓冲流(bis、bos、br、bw)

(一)概念

1、高效读写的缓冲流,转换编码的转换流,持久化存储对象的序列化流等。这些功能更为强大的流,都是在基本的流对象基础之上创建而来的,相当于是对基本流对象的一种增强。

2、缓冲流,也叫高效流,是对4个基本FileXxx流的增强。

3、按照数据类型分类:

①字节缓冲流:BufferedInputStream,BufferedOutputStream

②字符缓冲流:BufferedReader,BufferedWriter

4、缓冲流的基本原理:在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。

(二)bisbos字节缓冲流

1、构造方法

(1)BufferedInputStream(InputStream in):创建一个 新的缓冲输入流。

(2)BufferedOutputStream(OutputStream out):创建一个 新的缓冲输出流。

2、效率测试: 缓冲流读写方法与基本的流是一致的

通过复制大文件(375MB),测试效率。

(三)frfw字符缓冲流

1、构造方法

(1)BufferedReader(Reader in):创建一个 新的缓冲输入流。

(2)BufferedWriter(Writer out):创建一个新的缓冲输出流。

2、特有方法

字符缓冲流的基本方法与普通字符流调用方式一致,以下为特有方法:

1、BufferedReader:String readLine(): 读一行文字。

2、BufferedWriter:newLine(): 写一行行分隔符,由系统属性定义符号。

(四)综合案例:文本排序

1、题目:请将文本信息恢复:

如下

***

3.侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯,是以先帝简拔以遗陛下。愚以为宫中之事,事无大小,悉以咨之,然后施行,必得裨补阙漏,有所广益。

8.愿陛下托臣以讨贼兴复之效,不效,则治臣之罪,以告先帝之灵。若无兴德之言,则责攸之、祎、允等之慢,以彰其咎;陛下亦宜自谋,以咨诹善道,察纳雅言,深追先帝遗诏,臣不胜受恩感激。

4.将军向宠,性行淑均,晓畅军事,试用之于昔日,先帝称之曰能,是以众议举宠为督。愚以为营中之事,悉以咨之,必能使行阵和睦,优劣得所。

2.宫中府中,俱为一体,陟罚臧否,不宜异同。若有作奸犯科及为忠善者,宜付有司论其刑赏,以昭陛下平明之理,不宜偏私,使内外异法也。

1.先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也。

9.今当远离,临表涕零,不知所言。

6.臣本布衣,躬耕于南阳,苟全性命于乱世,不求闻达于诸侯。先帝不以臣卑鄙,猥自枉屈,三顾臣于草庐之中,咨臣以当世之事,由是感激,遂许先帝以驱驰。后值倾覆,受任于败军之际,奉命于危难之间,尔来二十有一年矣。

7.先帝知臣谨慎,故临崩寄臣以大事也。受命以来,夙夜忧叹,恐付托不效,以伤先帝之明,故五月渡泸,深入不毛。今南方已定,兵甲已足,当奖率三军,北定中原,庶竭驽钝,攘除奸凶,兴复汉室,还于旧都。此臣所以报先帝而忠陛下之职分也。至于斟酌损益,进尽忠言,则攸之、祎、允之任也。

5.亲贤臣,远小人,此先汉所以兴隆也;亲小人,远贤臣,此后汉所以倾颓也。先帝在时,每与臣论此事,未尝不叹息痛恨于桓、灵也。侍中、尚书、长史、参军,此悉贞良死节之臣,愿陛下亲之信之,则汉室之隆,可计日而待也。

***

2、案例分析:

(1)逐行读取文本信息

(2)解析文本信息到集合中

(3)遍历集合,按顺序,写出文本信息

3、案例实现:

 

二、转换流(isr、osw)

(一)概念

1、字符编码:

(1)按照某种规则,将字符存储到计算机中,称为编码。反之,将存储在计算机中的二进制数按照某种规则解析显示出来,称为解码。

(编码:字符(能看懂的)--字节(看不懂的)。解码:字节(看不懂的)-->字符(能看懂的) )

(2)字符编码Character Encoding:就是一套自然语言的字符与二进制数之间的对应规则。

(3)编码表:生活中文字和计算机中二进制的对应规则

2、字符集:

字符集Charset:也叫编码表。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等。

3、编码问题:乱码

在IDEA中,使用FileReader读取项目中的文本文件。由于IDEA的设置,是默认的UTF-8编码,所以没有任何问题。但是,当读取Windows系统中创建的文本文件时,由于Windows系统的默认是GBK编码,就会出现乱码。

(二)isr转换输入流 InputStreamReader类(Reader的子类)

1、概念

(1)InputStreamReader,是Reader的子类,是从字节流到字符流的桥梁。

(2)InputStreamReader读取字节,并使用指定的字符集将其解码为字符。

(3)InputStreamReader的字符集可以由名称指定,也可以接受平台的默认字符集。

2、构造方法

(1)InputStreamReader(InputStream in): 创建一个使用默认字符集的字符流。

(2)InputStreamReader(InputStream in, String charsetName): 创建一个指定字符集的字符流。

用法如下:指定编码读取

(三)osw转换输出流 OutputStreamWriter类(Writer的子类)

1、概念;

(1)OutputStreamWriter,是Writer的子类,是从字符流到字节流的桥梁。

(2)OutputStreamWriter读取字节,并使用指定的字符集将字符编码为字节。

(3)OutputStreamWriter的字符集可以由名称指定,也可以接受平台的默认字符集。

2、构造方法

(1)OutputStreamWriter(OutputStream in)`: 创建一个使用默认字符集的字符流。

(2)OutputStreamWriter(OutputStream in, String charsetName)`: 创建一个指定字符集的字符流。

用法如下:指定编码写出

(四)转换流练习:转换文件编码

1、题目:将GBK编码的文本文件,转换为UTF-8编码的文本文件

2、案例分析:

(1)指定GBK编码的转换流,读取文本文件。

(2)使用UTF-8编码的转换流,写出文本文件。

3、案例实现:

 

三、序列化(oos、ois)

(一)概念

1、序列化oos:Java 提供了一种对象序列化的机制。一个字节序列表示一个对象,该字节序列包含该`对象的数据`、`对象的类型`和`对象中存储的属性`等信息。字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息。

-- ObjectOutputStream类序列化两前提:(实现S接口、属性可序)

①该类必须实现Serializable接口,Serializable是一个标记接口,不实现此接口的类将不会使任何状态序列化或反序列化,会抛出NotSerializableException。

②该类的所有属性必须是可序列化的。transient瞬态修饰成员,不会被序列化。

2、反序列化ois:该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化。`对象的数据`、`对象的类型`和`对象中存储的数据`信息,都可以用来在内存中创建对象。

ObjectInputStream反序列化流,将序列化的原始数据恢复为对象。

(二)oos序列化 ObjectOutputStream类

1、构造方法

ObjectOutputStream(OutputStream out):创建一个指定OutputStream的ObjectOutputStream。

2、常用方法-序列化 writeObject

写出对象方法:final void writeObject(Object obj):将指定对象序列化写出。

(三)ois反序列化 ObjectInputSream类

1、构造方法:

ObjectInputStream(InputStream in):创建一个指定InputStream的ObjectInputStream。

2、常用方法-反序列化 readObject、UID

(1)直接反序列化:

对象的class文件,反序列化操作,调用ObjectInputStream读取对象的方法:

final Object readObject (): 读取一个对象。

(2)serialVersionUID验证

①当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化操作也会失败,抛出一个InvalidClassException异常。

发生这个异常的原因如下:

--该类的序列版本号与从流中读取的类描述符的版本号不匹配

--该类包含未知数据类型

--该类没有可访问的无参数构造方法

②Serializable接口给需要序列化的类,提供了一个序列版本号。

serialVersionUID该版本号的目的在于验证序列化的对象和对应类是否版本匹配。

(四)练习:序列化集合

1、题目:

(1)将存有多个自定义对象的集合序列化操作,保存到`list.txt`文件中。

(2)反序列化`list.txt` ,并遍历集合,打印对象信息。

2、案例分析:

(1)把若干学生对象 ,保存到集合中。

(2)把集合序列化。

(3)反序列化读取时,只需要读取一次,转换为集合类型。

(4)遍历集合,可以打印所有的学生信息

3、案例实现:

 

第四节、属性集和打印流

一、属性集Properties类(Hashtable的子类)

(一)概念

1、java.util.Properties继承于【Hashtable】,来表示一个持久的属性集。

2、键-值 结构存储数据,每个键及其对应值都是一个字符串。

3、该类也被许多Java类使用,比如获取系统属性时, System.getProperties方法是返回Properties对象。

(二)构造方法:

Properties():创建一个空的属性列表。

(三)常用方法(set、get、str、load)

1、Object setProperty(String key, String value):保存一对属性。 

2、String getProperty(String key):使用此属性列表中指定的键搜索属性值。

3、Set<String> stringPropertyNames():所有键的名称的集合。

(基本存储方法)

(4)load(InputStream inStream):从字节输入流(FileInputStream)中读取键值对。

(与流相关方法)

 

二、打印流PrintStream类

(一)概念:

控制台打印输出的调用print方法和println方法,来自于java.io.PrintStream类,该类能够方便地打印各种数据类型的值。

(二)构造方法

PrintStream(String fileName):指定的文件名 创建一个新的打印流。

(三)改变打印流向:

setOut(PrintStream ps) 改变打印流向至指定ps参数。

(sout也是PrintStream类型的,流向固定打印控制台)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值