JavaSE进阶——Day10 File类、IO流、字节流
该篇主要讲解Java中File类、IO流、字节流
File类
什么是File类?
- java.io.File类是java语言提供了用来描述 磁盘文件 和磁盘目录 的
创建
1 | public File(String path) |
1 | public File(String parent , String child)//基于父路径 和子路径 合并 后,生成File对象 |
MacOS不太一样:
1 | package file; |
mkdir和mkdirs就是一个可以创建父类文件,一个只能创建一个子文件
删除
1 | 文件对象.delete(); //返回值是布尔值 |
常用方法
练习
统计文件个数
1 | package file; |
io流
IO流解决程序中的什么问题?
- 把程序中存储在内存中的数据,写入到文件中(持久存储)
- 把磁盘文件中存储的数据,读取到内存中
IO流:
- I流: 把磁盘文件中存储的数据,读取到内存中(读数据)
- O流:把内存中的数据,写入到磁盘文件(写数据)
InputStream:输入流
- 字节输入流
- 字符输入流
OutputStream:输出流
- 字节输出流
- 字符输出流
字节流:万能流(所有类型的文件都可以读写)
字符流:通常用于针对纯文本文件进行读写操作
- 纯文本文件: 使用计算机中的记事本软件打开并看得懂的文件
File类,只能针对文件本身进行创建、删除(无法对文件中存储的内容进行操作的)
使用IO流,对文件中存储的内容进行操作(读、写)
IO流中的基础流:
- 字节流
- 字符流
IO流的作用:对磁盘上的文件进行读、写操作
- 读:输入流
- 写:输出流(把内存中的数据写入到磁盘文件中)
字节流输出流
字节输出流入门
FileOutputStream类 :
OutputStream
有很多子类,我们从最简单的一个子类开始。java.io.FileOutputStream
类是文件输出流,用于将数据写出到文件
构造方法 :
public FileOutputStream(File file)
:创建文件输出流以写入由指定的 File对象表示的文件。public FileOutputStream(String name)
: 创建文件输出流以指定的名称写入文件。
1
2
3
4
5
6
7
8
9
10public class FileOutputStreamConstructor throws IOException {
public static void main(String[] args) {
// 使用File对象创建流对象
File file = new File("a.txt");
FileOutputStream fos = new FileOutputStream(file);
// 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream("b.txt");
}
}字节输出流写数据快速入门
- 创建字节输出流对象。
- 写数据
- 释放资源
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
32package com.itheima.outputstream_demo;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
字节输出流写数据快速入门 :
1 创建字节输出流对象。
2 写数据
3 释放资源
*/
public class OutputStreamDemo1 {
public static void main(String[] args) throws IOException {
// 创建字节输出流对象
// 如果指定的文件不存在 , 会自动创建文件
// 如果文件存在 , 会把文件中的内容清空
FileOutputStream fos = new FileOutputStream("day11_demo\\a.txt");
// 写数据
// 写到文件中就是以字节形式存在的
// 只是文件帮我们把字节翻译成了对应的字符 , 方便查看
fos.write(97);
fos.write(98);
fos.write(99);
// 释放资源
// while(true){}
// 断开流与文件中间的关系
fos.close();
}
}
字节输出流写数据的方法
字节流写数据的方法
- 1 void write(int b) 一次写一个字节数据
- 2 void write(byte[] b) 一次写一个字节数组数据
- 3 void write(byte[] b, int off, int len) 一次写一个字节数组的部分数据
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
34package com.itheima.outputstream_demo;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
字节流写数据的3种方式
1 void write(int b) 一次写一个字节数据
2 void write(byte[] b) 一次写一个字节数组数据
3 void write(byte[] b, int off, int len) 一次写一个字节数组的部分数据
*/
public class OutputStreamDemo2 {
public static void main(String[] args) throws IOException {
// 创建字节输出流对象
FileOutputStream fos = new FileOutputStream("day11_demo\\a.txt");
// 写数据
// 1 void write(int b) 一次写一个字节数据
fos.write(97);
fos.write(98);
fos.write(99);
// 2 void write(byte[] b) 一次写一个字节数组数据
byte[] bys = {65, 66, 67, 68, 69};
fos.write(bys);
// 3 void write(byte[] b, int off, int len) 一次写一个字节数组的部分数据
fos.write(bys, 0, 3);
// 释放资源
fos.close();
}
}
写数据的换行和追加写入
1 | package com.itheima.outputstream_demo; |
1 | package com.itheima.outputstream_demo; |
字节输入流
字节输入流介绍
字节输入流类
- InputStream类 : 字节输入流最顶层的类 , 抽象类
--- FileInputStream类 : FileInputStream extends InputStream
构造方法
- public FileInputStream(File file) : 从file类型的路径中读取数据
- public FileInputStream(String name) : 从字符串路径中读取数据
步骤
- 创建输入流对象
- 读数据
释放资源
```
package com.itheima.inputstream_demo;import java.io.FileInputStream;
import java.io.IOException;/*
字节输入流写数据快速入门 : 一次读一个字节 第一部分 : 字节输入流类 InputStream类 : 字节输入流最顶层的类 , 抽象类 --- FileInputStream类 : FileInputStream extends InputStream 第二部分 : 构造方法 public FileInputStream(File file) : 从file类型的路径中读取数据 public FileInputStream(String name) : 从字符串路径中读取数据 第三部分 : 字节输入流步骤 1 创建输入流对象 2 读数据 3 释放资源
*/
public class FileInputStreamDemo1 {public static void main(String[] args) throws IOException { // 创建字节输入流对象 // 读取的文件必须存在 , 不存在则报错 FileInputStream fis = new FileInputStream("day11_demo\\a.txt"); // 读数据 , 从文件中读到一个字节 // 返回的是一个int类型的字节 // 如果想看字符, 需要强转 int by = fis.read(); System.out.println((char) by); // 释放资源 fis.close(); }
}
1
2
3
### 字节输入流读多个字节package com.itheima.inputstream_demo;
import java.io.FileInputStream;
import java.io.IOException;
/
字节输入流写数据快速入门 : 读多个字节
第一部分 : 字节输入流类
InputStream类 : 字节输入流最顶层的类 , 抽象类
—- FileInputStream类 : FileInputStream extends InputStream
第二部分 : 构造方法
public FileInputStream(File file) : 从file类型的路径中读取数据
public FileInputStream(String name) : 从字符串路径中读取数据
第三部分 : 字节输入流步骤
1 创建输入流对象
2 读数据
3 释放资源
/
public class FileInputStreamDemo2 {
public static void main(String[] args) throws IOException {
// 创建字节输入流对象
// 读取的文件必须存在 , 不存在则报错
FileInputStream fis = new FileInputStream(“day11_demo\a.txt”);
// 读数据 , 从文件中读到一个字节
// 返回的是一个int类型的字节
// 如果想看字符, 需要强转
// int by = fis.read();
// System.out.println(by);
// by = fis.read();
// System.out.println(by);
// by = fis.read();
// System.out.println(by);
//
// by = fis.read();
// System.out.println(by);
// by = fis.read();
// System.out.println(by);
// by = fis.read();
// System.out.println(by);
// 循环改进
int by;// 记录每次读到的字节
while ((by = fis.read()) != -1) {
System.out.print((char) by);
}
// 释放资源
fis.close();
}
}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
41
42
### 图片的拷贝
```java
package com.itheima.inputstream_demo;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
需求 : 把 "图片路径\xxx.jpg" 复制到当前模块下
分析:
复制文件,其实就把文件的内容从一个文件中读取出来(数据源),然后写入到另一个文件中(目的地)
数据源:
xxx.jpg --- 读数据 --- FileInputStream
目的地:
模块名称\copy.jpg --- 写数据 --- FileOutputStream
*/
public class FileInputStreamDemo2 {
public static void main(String[] args) throws IOException {
// 创建字节输入流对象
FileInputStream fis = new FileInputStream("D:\\传智播客\\安装包\\好看的图片\\liqin.jpg");
// 创建字节输出流
FileOutputStream fos = new FileOutputStream("day11_demo\\copy.jpg");
// 一次读写一个字节
int by;
while ((by = fis.read()) != -1) {
fos.write(by);
}
// 释放资源
fis.close();
fos.close();
}
}
异常的捕获处理
JDK7版本之前处理方式 : 手动释放资源
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
41
42
43
44
45
46
47
48
49package com.itheima.inputstream_demo;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
需求 : 对上一个赋值图片的代码进行使用捕获方式处理
*/
public class FileInputStreamDemo4 {
public static void main(String[] args) {
FileInputStream fis = null ;
FileOutputStream fos = null;
try {
// 创建字节输入流对象
fis = new FileInputStream("D:\\传智播客\\安装包\\好看的图片\\liqin.jpg");
// 创建字节输出流
fos = new FileOutputStream("day11_demo\\copy.jpg");
// 一次读写一个字节
int by;
while ((by = fis.read()) != -1) {
fos.write(by);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 释放资源
if(fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 释放资源
if(fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
JDK7版本优化处理方式 : 自动释放资源
JDK7优化后可以使用 try-with-resource 语句 , 该语句确保了每个资源在语句结束时自动关闭。
简单理解 : 使用此语句,会自动释放资源 , 不需要自己在写finally代码块了格式 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17格式 :
try (创建流对象语句1 ; 创建流对象语句2 ...) {
// 读写数据
} catch (IOException e) {
处理异常的代码...
}
举例 :
try (
FileInputStream fis1 = new FileInputStream("day11_demo\\a.txt") ;
FileInputStream fis2 = new FileInputStream("day11_demo\\b.txt") )
{
// 读写数据
} catch (IOException e) {
处理异常的代码...
}
代码实践
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
32package com.itheima.inputstream_demo;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
JDK7版本优化处理方式
需求 : 对上一个赋值图片的代码进行使用捕获方式处理
*/
public class FileInputStreamDemo5 {
public static void main(String[] args) {
try (
// 创建字节输入流对象
FileInputStream fis = new FileInputStream("D:\\传智播客\\安装包\\好看的图片\\liqin.jpg");
// 创建字节输出流
FileOutputStream fos = new FileOutputStream("day11_demo\\copy.jpg")
) {
// 一次读写一个字节
int by;
while ((by = fis.read()) != -1) {
fos.write(by);
}
// 释放资源 , 发现已经灰色 , 提示多余的代码 , 所以使用 try-with-resource 方式会自动关流
// fis.close();
// fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
字节输入流一次读一个字节数组
FileInputStream类 :
- public int read(byte[] b) : 从输入流读取最多b.length个字节的数据, 返回的是真实读到的数据个数
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54package com.itheima.inputstream_demo;
import javax.sound.midi.Soundbank;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
FileInputStream类 :
public int read(byte[] b):
1 从输入流读取最多b.length个字节的数据
2 返回的是真实读到的数据个数
*/
public class FileInputStreamDemo6 {
public static void main(String[] args) throws IOException {
// 创建字节输入流对象
FileInputStream fis = new FileInputStream("day11_demo\\a.txt");
// public int read(byte[] b):
// 1 从输入流读取最多b.length个字节的数据
// 2 返回的是真实读到的数据个数
byte[] bys = new byte[3];
// int len = fis.read(bys);
// System.out.println(len);// 3
// System.out.println(new String(bys));// abc
//
// len = fis.read(bys);
// System.out.println(len);// 2
// System.out.println(new String(bys));// efc
System.out.println("==========代码改进===============");
// int len = fis.read(bys);
// System.out.println(len);// 3
// System.out.println(new String(bys, 0, len));// abc
//
// len = fis.read(bys);
// System.out.println(len);// 2
// System.out.println(new String(bys, 0, len));// ef
System.out.println("==========代码改进===============");
int len;
while ((len = fis.read(bys)) != -1) {
System.out.print(new String(bys , 0 , len));
}
fis.close();
}
}对复制图片的代码进行使用一次读写一个字节数组的方式进行改进
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
37package com.itheima.inputstream_demo;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
需求 : 对复制图片的代码进行使用一次读写一个字节数组的方式进行改进
FileInputStream类 :
public int read(byte[] b):
1 从输入流读取最多b.length个字节的数据
2 返回的是真实读到的数据个数
*/
public class FileInputStreamDemo7 {
public static void main(String[] args) throws IOException {
// 创建字节输入流对象
FileInputStream fis = new FileInputStream("D:\\传智播客\\安装包\\好看的图片\\liqin.jpg");
// 创建字节输出流
FileOutputStream fos = new FileOutputStream("day11_demo\\copy.jpg");
byte[] bys = new byte[1024];
int len;// 每次真实读到数据的个数
int by;
while ((len = fis.read(bys)) != -1) {
fos.write(bys, 0, len);
}
// 释放资源
fis.close();
fos.close();
}
}
代码案例
单字节数据读写
1 | package demo; |
1 | package demo; |
字节缓冲流
在IO体系下,java提供了高效流(提高读写文件的效率)
字节缓冲流概述
字节缓冲流:
- BufferOutputStream:缓冲输出流
- BufferedInputStream:缓冲输入流
构造方法:
- 字节缓冲输出流:BufferedOutputStream(OutputStream out)
- 字节缓冲输入流:BufferedInputStream(InputStream in)
为什么构造方法需要的是字节流,而不是具体的文件或者路径呢?
- 字节缓冲流仅仅提供缓冲区,不具备读写功能 , 而真正的读写数据还得依靠基本的字节流对象进行操作
在IO体系下,java提供了高效流(提高读写文件的效率)
- 读文件:BufferedInputStream
- 写文件:BufferedOutputStream
创建:
在IO流中基础流只有两个:字节流、字符流
BufferedInputStream流的创建: 读数据
- 自己没有读数据的能力,需要依赖字节输入流实现读数据
1 | //构造方法: public BufferedInputStream( InputStream is ) |
BufferedOutputStream流的创建: 写数据
- 自己没有写数据的能力,需要依赖字节输出流实现读数据
1 | //构造方法: public BufferedOutputStream( OutputStream os ) |
案例:
1 | package buffered; |
Properties集合类「重点!!!」
概述
properties是一个Map体系的集合类
public class Properties extends Hashtable <Object,Object>
为什么在IO流部分学习Properties
- Properties中有跟IO相关的方法
当做双列集合使用
- 不需要加泛型 , 工作中只存字符串
基本使用
Properties类:
- 作为Map集合的子类存在(存储的数据:key、value)
- 可以结合IO流使用 (读、写)
Properties类的基本使用:
- 作为集合使用
- 结合IO流使用
构造方法:
1 | Properties prop = new Properties(); |
常用方法:
1 | //向Properties集合中存储:key、value |
1 | package com.itheima.properties_demo; |
Properties作为集合的特有方法
- Object setProperty(String key, String value) 设置集合的键和值,都是String类型,相当于put方法
- String getProperty(String key) 使用此属性列表中指定的键搜索属性 , 相当于get方法
- Set
stringPropertyNames() 从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串 , 相当于keySet方法
1 | package com.itheima.properties_demo; |
properties中和IO相关的方法
- void load(InputStream inStream) 以字节流形式 , 把文件中的键值对, 读取到集合中
- void load(Reader reader) 以字符流形式 , 把文件中的键值对, 读取到集合中
- void store(OutputStream out, String comments) 把集合中的键值对,以字节流形式写入文件中 , 参数二为注释
- void store(Writer writer, String comments) 把集合中的键值对,以字符流形式写入文件中 , 参数二为注释
1 | package com.itheima.properties_demo; |
1 | package com.itheima.properties_demo; |
补充
在开发中,通常会使用到配置文件,而配置文件格式通常分为:
- XML文件
- properties文件
- ….
Properties类的作用:
- 读取开发中使用的到.properties配置文件
- properties配置文件中的数据是以key/value形式体现
- 把properties配置文件中的key,存储到Properties类中的key元素下
- 把properties配置文件中的value,存储到Properties类中的value元素下
递归
什么是递归?
- 递归是应用于方法上的解决方案:方法自己调用自己
递归 = 递进 + 回归
- 递进 :前进
- 回归: 后退
递归案例
1 | package digui; |
递归的弊端:
当递归调用的方法过多时,会造成栈内存的溢出
解决方案: 队列结构
1
2
3
4
5
6
7
81. 获取所有的File对象,存储到集合中
2. 遍历集合
判断:是文件
判断:是否为java文件
判断:是目录
存储到集合中
细节: 从集合中获取一个数据后,该数据在集合中就无用了
综合案例
1 | package digui; |