0%

IO流概述

io流读写操作

IO流读写数据

IO输入输出流:输入/输出流。
Input:输入。
Output:输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
引入:
File类只能操作文件对象本身,不能读写文件对象的内容。
读写数据内容,应该使用IO流。

IO流是一个水流模型:IO理解成水管,把数据理解成水流。

IO流的分类:
按照流的方向分为:输入流,输出流。
(1)输出流:以内存为基准,把内存中的数据写出到磁盘文件或者网络介质中去的流称为输出流。
输出流的作用:写数据到文件,或者写数据发送给别人。

(2)输入流:以内存为基准,把磁盘文件中的数据或者网络中的数据读入到内存中去的流称为输入流。
输入流的作用:读取数据到内存。

按照流的内容分为: 字节流,字符流。
(1)字节流:流中的数据的最小单位是一个一个的字节,这个流就是字节流。
(2)字符流:流中的数据的最小单位是一个一个的字符,这个流就是字符流。(针对于文本内容)


所以流大体分为四大类:
字节输入流:以内存为基准,把磁盘文件中的数据或者网络中的数据以一个一个的字节的形式读入到内存中去的流称为字节输入流。
字节输出流:以内存为基准,把内存中的数据以一个一个的字节写出到磁盘文件或者网络介质中去的流称为字节输出流。
字符输入流:以内存为基准,把磁盘文件中的数据或者网络中的数据以一个一个的字符的形式读入到内存中去的流称为字符输入流。
字符输出流:以内存为基准,把内存中的数据以一个一个的字符写出到磁盘文件或者网络介质中去的流称为字符输出流。

小结:
IO流是读写传输数据的,IO流有很多种,每种流有自己的功能特点。

字节流

1
2
3
4
5
IO流的体系:
字节流 字符流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter (子类实现类)

字节输入流的使用

1
2
3
4
5
6
7
8
a.FileInputStream文件字节输入流。
-- 作用:以内存为基准,把磁盘文件中的数据按照字节的形式读入到内存中的流。
简单来说,就是按照字节读取文件数据到内存。
-- 构造器:
1.public FileInputStream(File path):创建一个字节输入流管道与源文件对象接通。
2.public FileInputStream(String pathName):创建一个字节输入流管道与文件路径对接。
-- 方法:
1.public int read():每次读取一个字节返回!读取完毕会返回-1。

小结:
一个一个字节读取英文和数字没有问题。
但是一旦读取中文输出无法避免乱码,因为会截断中文的字节。
一个一个字节的读取数据,性能也较差,所以禁止使用此方案!

按照字节数组读取

1
2
3
4
5
6
7
8
9
10
11
a.FileInputStream文件字节输入流。
-- 作用:以内存为基准,把磁盘文件中的数据按照字节的形式读入到内存中的流。
简单来说,就是按照字节读取文件数据到内存。
-- 构造器:
1.public FileInputStream(File path):创建一个字节输入流管道与源文件对象接通。
2.public FileInputStream(String pathName):创建一个字节输入流管道与文件路径对接。
-- 方法:
1.public int read():每次读取一个字节返回!读取完毕会返回-1。
2.public int read(byte[] buffer):从字节输入流中读取字节到字节数组中去,
返回读取的字节数量,没有字节可读返回-1。

    小结:
      public int read(byte[] buffer):从字节输入流中读取字节到字节数组中去,
            返回读取的字节数量,没有字节可读返回-1。
       使用字节数组读取内容,效率可以。
       但是使用字节数组读取文本内容输出,也无法避免中文读取输出乱码的问题。

解决字节输入流读取中文内容输出乱码的问题

1
2
3
4
5
引入:
一个一个字节读取中文输出
一个一个字节数组读取中文输出均无法避免乱码。
如何实现读取可以避免乱码呢?
1.定义一个字节数组与文件的大小刚刚一样大,然后一桶水读取全部字节数据再输出!

小结:
定义一个字节数组与文件的大小刚刚一样大,然后一桶水读取全部字节数据再输出!
可以避免中文读取输出乱码,但是如果读取的文件过大,会出现内存溢出!!

字节流并不适合读取文本文件内容输出,读写文件内容建议使用字符流

字节输出流的使用

1
2
3
4
5
IO流的体系:
字节流 字符流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter (实现类)
1
2
3
4
5
6
7
8
9
10
11
12
13
a.FileOutputStream文件字节输出流
-- 作用:以内存为基准,把内存中的数据,按照字节的形式写出到磁盘文件中去。
简单来说,把内存数据按照字节写出到磁盘文件中去。
-- 构造器:
public FileOutputStream(File file):创建一个字节输出流管道通向目标文件对象。
public FileOutputStream(String file):创建一个字节输出流管道通向目标文件路径。
public FileOutputStream(File file , boolean append):创建一个追加数据的字节输出流管道通向目标文件对象。
public FileOutputStream(String file , boolean append):创建一个追加数据的字节输出流管道通向目标文件路径。
-- 方法:
public void write(int a):写一个字节出去 。
public void write(byte[] buffer):写一个字节数组出去。
public void write(byte[] buffer , int pos , int len):写一个字节数组的一部分出去。
参数一,字节数组;参数二:起始字节索引位置,参数三:写多少个字节数出去。

小结:
字节输出流只能写字节出去。
字节输出流默认是覆盖数据管道。
换行用: os.write(“\r\n”.getBytes());
关闭和刷新:刷新流可以继续使用,关闭包含刷新数据但是流就不能使用了!

追加数据管道

1
FileOutputStream字节输出流每次启动写数据的时候都会先清空之前的全部数据,从新写入。

小结:
覆盖数据管道: OutputStream os = new FileOutputStream(“Day09Demo/out05”);
追加数据的管道:OutputStream os = new FileOutputStream(“Day09Demo/out05” , true);
参数二代表了此管道是追加数据的管道,不会覆盖之前的数据!

JDK 1.7开始之后释放资源的新方式

1
2
3
4
5
6
7
8
9
10
11
try-with-resources:
try(
// 这里只能放置资源对象,用完会自动调用close()关闭
){

}catch(Exception e){
e.printStackTrace();
}
什么是资源?
资源类一定是实现了Closeable接口,实现这个接口的类就是资源
有close()方法,try-with-resources会自动调用它的close()关闭资源。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void main(String[] args) {
try(
/** (1)创建一个字节输入流管道与源文件接通。 */
InputStream is = new FileInputStream("D:\\itcast\\图片资源\\meinv.jpg");
/** (2)创建一个字节输出流与目标文件接通。*/
OutputStream os = new FileOutputStream("D:\\itcast\\meimei.jpg");
/** (5)关闭资源!是自动进行的 */
){
/** (3)创建一个字节数组作为桶*/
byte[] buffer = new byte[1024];
/** (4)从字节输入流管道中读取数据,写出到字节输出流管道即可。*/
int len = 0;
while((len = is.read(buffer)) != -1){
// 读取多少就倒出多少
os.write(buffer, 0 , len);
}
System.out.println("复制完成!");
}catch (Exception e){
e.printStackTrace();
}
}

字符流

字符输入流的使用

1
2
3
4
5
IO流的体系:
字节流 字符流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter (实现类)

小结:
字符流一个一个字符的读取文本内容输出,可以解决中文读取输出乱码的问题。
字符流很适合操作文本文件内容。
但是:一个一个字符的读取文本内容性能较差!!

按照字符数组读取

1
2
3
4
5
6
7
8
9
c.FileReader:文件字符输入流。
-- 作用:以内存为基准,把磁盘文件的数据以字符的形式读入到内存。
简单来说,读取文本文件内容到内存中去。
-- 构造器:
public FileReader(File file):创建一个字符输入流与源文件对象接通。
public FileReader(String filePath):创建一个字符输入流与源文件路径接通。
-- 方法:
public int read(): 读取一个字符的编号返回! 读取完毕返回-1
public int read(char[] buffer):读取一个字符数组,读取多少个字符就返回多少个数量,读取完毕返回-1

小结:
字符流按照字符数组循环读取数据,可以解决中文读取输出乱码的问题,而且性能也较好!!

字符输出流的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
d.FileWriter文件字符输出流的使用。
-- 作用:以内存为基准,把内存中的数据按照字符的形式写出到磁盘文件中去。
简单来说,就是把内存的数据以字符写出到文件中去。
-- 构造器:
public FileWriter(File file):创建一个字符输出流管道通向目标文件对象。
public FileWriter(String filePath):创建一个字符输出流管道通向目标文件路径。
public FileWriter(File file,boolean append):创建一个追加数据的字符输出流管道通向目标文件对象。
public FileWriter(String filePath,boolean append):创建一个追加数据的字符输出流管道通向目标文件路径。
-- 方法:
a.public void write(int c):写一个字符出去
b.public void write(String c)写一个字符串出去:
c.public void write(char[] buffer):写一个字符数组出去
d.public void write(String c ,int pos ,int len):写字符串的一部分出去
e.public void write(char[] buffer ,int pos ,int len):写字符数组的一部分出去

小结:
字符输出流可以写字符数据出去,总共有5个方法写字符。
覆盖管道:
Writer fw = new FileWriter(“Day10Demo/src/dlei03.txt”); // 覆盖数据管道
追加数据管道:
Writer fw = new FileWriter(“Day10Demo/src/dlei03.txt”,true); // 追加数据管道
换行:
fw.write(“\r\n”); // 换行
读写字符文件数据建议使用字符流。

缓冲流的概述和分类

1
2
3
4
5
6
7
8
9
10
11
12
13
    字节流                                             字符流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter(实现类,低级流,原始流)
BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter(实现类,缓冲流)

什么是缓冲流:缓冲流可以提高字节流和字符流的读写数据的性能。
缓冲流分为四类:
(1)BufferedInputStream:字节缓冲输入流,可以提高字节输入流读数据的性能。
(2)BufferedOutStream: 字节缓冲输出流,可以提高字节输出流写数据的性能。
(3)BufferedReader: 字符缓冲输入流,可以提高字符输入流读数据的性能。
(4)BufferedWriter: 字符缓冲输出流,可以提高字符输出流写数据的性能。

字节缓冲输入流的使用

1
2
3
4
5
6
a.字节缓冲输入流:BufferedInputStream
-- 作用:可以把低级的字节输入流包装成一个高级的缓冲字节输入流管道,
从而提高字节输入流读数据的性能。
-- 构造器: public BufferedInputStream(InputStream in)
-- 原理:缓冲字节输入流管道自带了一个8KB的缓冲池,每次可以直接借用操作系统的功能最多提取8KB
的数据到缓冲池中去,以后我们直接从缓冲池读取数据,所以性能较好!

小结:
字节缓冲输入流:BufferedInputStream
可以把低级的字节输入流包装成一个高级的缓冲字节输入流管道,从而提高字节输入流读数据的性能。
功能几乎无变化。

字节缓冲输出流的使用

1
2
3
4
字节缓冲输出流:BufferedOutputStream
-- 作用:可以把低级的字节输出流包装成一个高级的缓冲字节输出流,从而提高写数据的性能。
-- 构造器:public BufferedOutputStream(OutputStream os)
-- 原理:缓冲字节输出流自带了8KB缓冲池,数据就直接写入到缓冲池中去,性能极高了!

小结:
字节缓冲输出流可以把低级的字节输出流包装成一个高级的缓冲字节输出流,从而提高写数据的性能。
功能几乎不变。

字符缓冲输入流的使用

1
2
3
4
5
6
7
8
字符缓冲输入流:BufferedReader
-- 作用:字符缓冲输入流可以把字符输入流包装成一个高级的缓冲字符输入流,
可以提高字符输入流读数据的性能。
-- 构造器:public BufferedReader(Reader reader):
-- 原理:缓冲字符输入流默认会有一个8K的字符缓冲池,可以提高读字符的性能。
-- 缓冲字符输入流除了提高了字符输入流的读数据性能,
缓冲字符输入流还多了一个按照行读取数据的功能(重点):
public String readLine(): 读取一行数据返回,读取完毕返回null;

小结:
字符缓冲输入流可以把字符输入流包装成一个高级的缓冲字符输入流,
可以提高字符输入流读数据的性能。
除此之外多了一个按照行读取数据的功能:
public String readLine(): 读取一行数据返回,读取完毕返回null;

字符缓冲输出流的使用

1
2
3
4
5
6
字符缓冲输出流:BufferedWriter
-- 作用:把字符输出流包装成一个高级的缓冲字符输出流,提高写字符数据的性能。
-- 构造器:public BufferedWriter(Writer writer):
-- 原理:高级的字符缓冲输出流多了一个8k的字符缓冲池,写数据性能极大提高了!
-- 字符缓冲输出流除了提高字符输出流写数据的性能,还多了一个换行的特有功能:
public void newLine():新建一行。

小结:
缓冲字符输出流可以把低级的字符输出流进行包装。提高了写字符的性能。
多了一个换行的功能:public void newLine():新建一行。

转换流

1
2
3
4
5
6
        字节流                                    字符流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter(实现类)
BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter(实现类,缓冲流)
InputStreamReader OutputStreamWriter

字符输入转换流的使用

1
2
3
4
5
6
7
8
字符输入转换流InputStreamReader:
-- 作用:可以解决字符流读取不同编码乱码的问题。
可以把原始的字节流按照当前默认的代码编码转换成字符输入流。
也可以把原始的字节流按照指定编码转换成字符输入流

-- 构造器:
public InputStreamReader(InputStream is):可以使用当前代码默认编码转换成字符流,几乎不用!
public InputStreamReader(InputStream is,String charset):可以指定编码把字节流转换成字符流

小结:
字符输入转换流可以把字节输入流按照默认编码转换成字符输入流。
– Reader isr = new InputStreamReader(is); // 使用当前代码默认编码UTF-8转换成字符流,几乎不用!
字符输入转换流也可以指定编码把字节输入流转换成字符输入流。
– Reader isr = new InputStreamReader(is,”GBK”); // 指定编码把字节流转换成字符流
字符输入转换流可以解决不同编码读取乱码的问题!

字符输出转换流的使用

1
2
3
4
5
6
字符输出转换流:OutputStreamWriter
-- 作用:可以指定编码把字节输出流转换成字符输出流。
可以指定写出去的字符的编码。
-- 构造器:
public OutputStreamWriter(OutputStream os) : 用当前默认编码UTF-8把字节输出流转换成字符输出流
public OutputStreamWriter(OutputStream os , String charset):指定编码把字节输出流转换成字符输出流

小结:
字符输出转换流可以指定编码把字节输出流转换成字符输出流。
从而实现指定写出去的字符编码!

对象序列化技术

对象序列化:就是把Java对象数据直接存储到文件中去。 对象 => 文件中
对象反序列化:就是把Java对象的文件数据恢复到Java对象中。 文件中 => 对象

1
2
3
4
5
6
7
         字节流                                    字符流
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter(实现类)
BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter(实现类,缓冲流)
InputStreamReader OutputStreamWriter
ObjectInputStream ObjectOutputStream

对象字节输出流

1
2
3
4
对象序列化流(对象字节输出流):ObjectOutputStream
-- 作用:把内存中的Java对象数据保存到文件中去。
-- 构造器: public ObjectOutputStream(OutputStream out)
-- 序列化方法:public final void writeObject(Object obj)

注意:对象如果想参与序列化,对象必须实现序列化接口 implements Serializable ,否则序列化失败!

小结:
注意:对象如果想参与序列化,对象必须实现序列化接口 implements Serializable ,否则序列化失败!
对象序列化使用的流是对象字节输出流:ObjectOutputStream

对象字节输入流

1
2
3
4
5
6
7
8
9
10
11
对象反序列化(对象字节输入流):ObjectInputStream
-- 作用:读取序列化的对象文件恢复到Java对象中。
-- 构造器:public ObjectInputStream(InputStream is)
-- 方法:public final Object readObject()

如果一个字段不想参数序列化:
transient修饰该成员变量,它将不参与序列化!
序列化版本号:
// 加入序列版本号
private static final long serialVersionUID = 2L;
必须序列化使用的版本号和反序列化使用的版本号一致才可以正常反序列化!否则报错!

小结:
对象反序列化可以把对象序列化的文件数据恢复成Java对象。
对象反序列化使用的流是:ObjectInputStream.

打印流

1
2
3
4
5
6
打印流的作用:
1.可以方便,快速的写数据出去。
2.可以实现打印啥出去,就是啥出去。
打印流的构造器:
public PrintStream(OutputStream os):
public PrintStream(String filepath):

小结:
打印流可以方便,且高效的打印各种数据。
PrintStream不光可以打印数据,还可以写”字节数据”出去。
PrintWriter不光可以打印数据,还可以写”字符数据”出去。

打印流改变输出的流向

1
2
System:
public static void setOut(PrintStream out) :让系统的输出流向打印流。
1
2
3
4
5
6
7
8
9
10
11
public static void main(String[] args) throws Exception {
System.out.println("==0==");
PrintStream ps = new PrintStream("Day10Demo/src/log.txt");
System.setOut(ps); // 让系统的输出流向打印流。

System.out.println("==itheima1==");
System.out.println("==itheima2==");
System.out.println("==itheima3==");
System.out.println("==itheima4==");
System.out.println("==itheima5==");
}

Properties的概述和使用

1
2
3
4
5
6
Properties:属性集对象。
其实就是一个Map集合。也就是一个键值对集合。但是我们一般不会当集合使用,
因为有HashMap。
Properties核心作用:
Properties代表的是一个属性文件,可以把键值对的数据存入到一个属性文件中去。
属性文件:后缀是.properties结尾的文件,里面的内容都是 key=value。

很多大型框架技术中,属性文件都是很重要的系统配置文件。
users.properties
admin=123456
dlei=dlei

1
2
3
4
5
6
7
8
Properties的方法:
-- public Object setProperty(String key, String value) : 保存一对属性。
-- public String getProperty(String key) :使用此属性列表中指定的键搜索属性值
-- public Set<String> stringPropertyNames() :所有键的名称的集合
-- public void store(OutputStream out, String comments):保存数据到属性文件中去
-- public void store(Writer fw, String comments):保存数据到属性文件中去
-- public synchronized void load(InputStream inStream):加载属性文件的数据到属性集对象中去
-- public synchronized void load(Reader fr):加载属性文件的数据到属性集对象中去

小结:
属性集对象Properties实际上是一个Map集合,可以实现把键值对数据保存到
属性文件中去!!

Commons-io

1
2
3
4
5
6
7
8
9
10
11
12
13
14
什么是Commons-io包?
commons-io是apache开源基金组织提供的一组有关IO操作的类库,
可以挺提高IO功能开发的效率。commons-io工具包提供了很多有关io操作的类,
见下表:
| 包 | 功能描述 |
| ----------------------------------- | :------------------------------------------- |
| org.apache.commons.io | 有关Streams、Readers、Writers、Files的工具类 |
| org.apache.commons.io.input | 输入流相关的实现类,包含Reader和InputStream |
| org.apache.commons.io.output | 输出流相关的实现类,包含Writer和OutputStream |
| org.apache.commons.io.serialization | 序列化相关的类
步骤:
1. 下载commons-io相关jar包;http://commons.apache.org/proper/commons-io/
2. 把commons-io-2.6.jar包复制到指定的Module的lib目录中
3. 将commons-io-2.6.jar加入到classpath中

小结:
IOUtils和FileUtils可以方便的复制文件和文件夹!!

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) throws Exception {
// 1.完成文件复制!
IOUtils.copy(new FileInputStream("Day13Demo/src/books.xml"), new FileOutputStream("Day13Demo/new.xml"));
// 2.完成文件复制到某个文件夹下!
FileUtils.copyFileToDirectory(new File("Day13Demo/src/books.xml"), new File("D:/itcast"));
// 3.完成文件夹复制到某个文件夹下!
FileUtils.copyDirectoryToDirectory(new File("D:\\itcast\\约吧图片服务器") , new File("D:\\"));

// Java从1.7开始提供了一些nio, 自己也有一行代码完成复制的技术。
Files.copy(Paths.get("Day13Demo/src/books.xml")
, new FileOutputStream("Day13Demo/new11.txt"));
}

File类的概述和API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
File类:代表操作系统的文件对象。
File类:是用来操作操作系统的文件对象的,删除文件,获取文件信息,创建文件(文件夹)...
广义来说操作系统认为文件包含(文件和文件夹)

File类的创建文件对象的API:
包:java.io.File
(1)构造器:
-- public File(String pathname):根据路径获取文件对象
-- public File(String parent , String child):根据父路径和文件名称获取文件对象!
-- public File(File parent , String child)

File类创建文件对象的格式:
a.File f = new File("绝对路径/相对路径");
绝对路径:从磁盘的的盘符一路走到目的位置的路径。
-- 绝对路径依赖具体的环境,一旦脱离环境,代码可能出错!!
-- 一般是定位某个操作系统中的某个文件对象。
相对路径:不带盘符的。(重点)
-- 默认是直接相对到工程目录下寻找文件的。
-- 相对路径只能用于寻找工程下的文件。
-- 能用相对路径就应该尽量使用,可以跨平台!

b.File f = new File("文件对象/文件夹对象");
广义来说:文件是包含文件和文件夹的。

小结:
创建文件对象可以用绝对路径也可以用相对路径。
相对路径只能用于寻找工程下的文件。
文件对象可以表示文件也可以表示文件夹!

File类的获取功能的API

1
2
3
4
- public String getAbsolutePath()  :返回此File的绝对路径名字符串。
- public String getPath() : 获取创建文件对象的时候用的路径
- public String getName() : 返回由此File表示的文件或目录的名称。
- public long length() : 返回由此File表示的文件的长度。

File类的判断功能的方法

1
2
3
- public boolean exists() :此File表示的文件或目录是否实际存在。
- public boolean isDirectory():此File表示的是否为目录。
- public boolean isFile() :此File表示的是否为文件

File类的创建和删除的方法

1
2
3
4
5
- public boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,
创建一个新的空文件。 (几乎不用的,因为以后文件都是自动创建的!)
- public boolean delete() :删除由此File表示的文件或目录。 (只能删除空目录)
- public boolean mkdir() :创建由此File表示的目录。(只能创建一级目录)
- public boolean mkdirs() :可以创建多级目录(建议使用的)

File针对目录的遍历

1
2
3
4
- public String[] list():
获取当前目录下所有的"一级文件名称"到一个字符串数组中去返回。
- public File[] listFiles()(常用):
获取当前目录下所有的"一级文件对象"到一个文件对象数组中去返回(重点)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static void main(String[] args) {
File dir = new File("D:\\leet");
// a.获取当前目录对象下的全部一级文件名称到一个字符串数组返回。
String[] names = dir.list();
for (String name : names) {
System.out.println(name);
}
// b.获取当前目录对象下的全部一级文件对象到一个File类型的数组返回。
File[] files = dir.listFiles();
for (File file : files) {
System.out.println(file.getAbsolutePath());
}

// ---------拓展------------
File f1 = new File("D:\\leet\\Code\\actframework\\.gitignore");
long time = f1.lastModified(); // 最后修改时间!
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(time));
}

递归实现文件搜索(非规律递归)

分析:
(1)定义一个方法用于做搜索。
(2)进入方法中进行业务搜索分析。
小结:
非规律化递归应该按照业务流程开发!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public static void main(String[] args) {
// 搜索调用方法
searchFiles(new File("D:\\leet\\AppData") , "notepad++.exe");
}

/**
* 去某个目录下搜索某个文件 🐺
* @param dir 搜索文件的目录。
* @param fileName 搜索文件的名称。
*/
public static void searchFiles(File dir , String fileName){
// 1.判断是否存在该路径,是否是文件夹
if(dir.exists() && dir.isDirectory()){
// 2.提取当前目录下的全部一级文件对象
File[] files = dir.listFiles(); // null/[]
// 3.判断是否存在一级文件对象(判断是否不为空目录)
if(files!=null && files.length > 0){
// 4.判断一级文件对象
for (File f : files) {
// 5.判断file是文件还是文件夹
if(f.isFile()){
// 6.判断该文件是否为我要找的文件对象
if(f.getName().contains(fileName)){
System.out.println(f.getAbsolutePath());
try {
// 启动它(拓展)
Runtime r = Runtime.getRuntime();
r.exec(f.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
}
}else{
// 7.该文件是文件夹,文件夹要递归进入继续寻找
searchFiles(f ,fileName);
}
}
}
}
}

字符集/编码集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
字符集:各个国家为自己国家的字符取的一套编号规则。
计算机的底层是不能直接存储字符的。
计算机的底层只能存储二进制。010101
二进制就是可以转成10进制的。10进制就是整数编号。
101 = 1*2^0 + 0*2^1 + 1*2^2 = 5

结论:计算机的底层可以存储编号。

1B = 8b 计算机中的最小单位是字节B.

美国人:
8个开关一组就可以编码字符。 1个字节。
2^8 = 256
一个字节存储一个字符完全够用了。

a 97
b 98

A 65
B 66

0 48
1 49
这套编码是ASCII编码。

英文和数字在底层存储的时候都是采用1个字节存储的。

中国人:
中国人的字符很多:9万左右字符。
中国人一般采用2个字节编码一个中文字符。
这套编码叫:GBK编码。
它也必须兼容ASCII编码表。
....

美国人:
我来收集全球所有的字符,统一编号。这套编码叫 Unicode编码(万国码)
UTF-8就是变种形式。
UTF-8一个中文一般占3个字节。
它也必须兼容ASCII编码表。

小结:
英文和数字在任何编码集中都是一样的,都占1个字节。
GBK编码中,1个中文字符一般占2个字节。
UTF-8编码中,1个中文字符一般占3个字节。
技术人员都应该使用UTF-8编码!

​ 编码前与编码后的编码集必须一致才不会乱码!!
​ GBK 我爱你[oo oo oo] GBK 不会乱码!

​ GBK 我爱你[oo oo oo] UTF-8 会乱码

​ 英文和数字在任何编码集中可以通用,不会乱码!!