0-引言
首先我们要思考为什么要学File和IO流。
- 那么我们看一看以前存储数据的方案。
- 变量:double money=99.5;
- 数组:int[] age=new int[100];
- 对象:Student s=new Student();
- 集合:List<Student> students=new ArrayList<>();
可以看到,我们以前这些数据都是放在内存中,这些数据容器都在内存中,一旦程序结束、断电,数据就没有。
可我们有很多数据需要持久化的保存,于是我们引进了File和IO流的概念。
File(文件)
- 文件可以长久保存数据
- 文件在电脑磁盘中保存,即便断电,或者程序终止,文件中的数据也不会丢失。
- File是java.io包下的类,File类的对象,用于代表当前操作系统的文件(可以是文件、或文件夹)。
- 那既然是类的对象,就一定会提供我们很多方法,比如获取文件信息(大小、文件名、修改时间)、判断文件的类型、创建文件/文件夹、删除文件/文件夹...
- 注意:File只能对文件本身进行操作,不能读写文件里面存储的数据。
IO流
- 用于读写数据的(可以读写文件,或网络中的数据)
1-File
File类的对象可以代表文件/文件夹,并可以调用其提供的方法对象文件进行操作。
1.1-File提供的常用方法
我就不把方法列表格展示了,咱们各种语法格式直接代码里见。
public static void main(String[] args) throws Exception {
//目标:创建File创建对象代表文件(文件/目录),搞清楚其提供的对文件进行操作的方法。
//1.创建File对象,去获取某个文件的信息
File f1=new File("F:/img/12.jpg");
System.out.println(f1.length());//获取文件大小
System.out.println(f1.getName());//获取文件名
System.out.println(f1.isFile());//判断是否是文件
System.out.println(f1.isDirectory());//判断是否是目录 false
//2.使用相对路径定位文件,相对路径是相对当前java工程
//只要带盘符的路径,都是绝对路径F:/img/12.jpg
//相对路径:不带盘符,默认是到你的idea工程下直接寻找文件的,一般用来找到资源文件。
File f2=new File("day03-file-io/src/xunshan01.txt");
System.out.println(f2.length());
//3.创建对象代表不存在的文件路径。
File f3=new File("F:/img/createdemo.txt");
System.out.println(f3.exists());//判断文件是否存在
System.out.println(f3.createNewFile());//创建出这个文件
//4.创建对象代表不存在的文件夹路径
File f4=new File("F:/img/createdir");
System.out.println(f4.exists());//判断文件夹是否存在
System.out.println(f4.mkdir());//创建文件夹 mkdir只能创建一级文件夹
File f5 = new File("F:/img/createdir/createdir1/createdir2");
System.out.println(f5.mkdirs());//创建多级文件夹 mkdirs可以创建多级文件夹
//5.创建File对象代表存在的文件,然后删除它
File f6=new File("F:/img/createdemo.txt");
System.out.println(f6.delete());//删除文件,返回是否删除成功
//6.创建File对象代表存在的文件夹,然后删除它
File f7=new File("F:/img/createdir");
System.out.println(f7.delete());//删除文件夹,返回是否删除成功 默认只能删除文件或空文件夹,不能删除有内容的文件夹
//7.获取某个目录下的全部一级文件名
File f8=new File("F:/img");
String[] list = f8.list();
for (String s : list) {
System.out.println(s);
}
//8.获取某个目录下的全部一级文件对象
File[] files = f8.listFiles();
for (File file : files) {
System.out.println(file.getAbsolutePath());//获取绝对路径
}
}

1.2-File提供的遍历文件夹的方法
使用listFiles方法时的注意事项:
- 当主调是文件,或者路径不存在时,返回null
- 当主调是空文件夹时,返回一个长度为0的数组
- 当主调是一个有内容的文件夹时,将里面所有一级文件和文件夹的路径放在File数组中返回
- 当主调是一个文件夹,里面有隐藏文件时,将里面所有文件和文件夹的路径放在File数组中返回,包含隐藏文件
- 当主调是一个文件夹,但是没有权限访问该文件夹时,返回null
public static void main(String[] args) {
//目标:掌握File遍历一级文件对象的操作
//当主调是文件,或者路径不存在时,返回null
File dir = new File("E:/img/abc.txt");
File[] files = dir.listFiles();
System.out.println(files);
//当主调是空文件夹时,返回一个长度为0的数组
File dir2= new File("F:/img/createdir");
File[] files1 = dir2.listFiles();
System.out.println(Arrays.toString(files1));
//当主调是一个有内容的文件夹时,将里面所有一级文件和文件夹的路径放在File数组中返回
File dir3= new File("F:/img");
File[] files2 = dir3.listFiles();
System.out.println(Arrays.toString(files2));
}

2-方法递归
2.1-认识递归
什么是递归?
- 递归是一种算法,在程序设计语言中广泛应用。
- 从形式上来说:方法调用自身的形式称为方法递归(recursion)。
递归的形式
- 直接递归:方法自己调用自己
- 间接递归:方法调用其他方法,其他方法又回调方法自己。
使用递归需要注意的问题
- 递归如果没有控制好终止,会出现死循环,导致内存栈溢出错误。

2.2-递归算法和其执行流程
因为递归的思想非常抽象,我们从数学上着手讲递归的算法,做一个小案例。
2.2.1-案例·计算n的阶乘
需求:
计算n的阶乘,5的阶乘=1*2*3*4*5,6的阶乘=1*2*3*4*5*6
分析:
- 假如我们认为存在一个公式f(n)=1*2*3*4*5*...*(n-1)*n;
- 那么公式等价形式就是:f(n)=f(n-1)*n
- 如果求1~5的阶乘的结果,我们手工应该如何应用上述公式计算?
→f(5)=f(4)*5
→f(3)=f(2)*3
→f(4)=f(3)*4
→f(2)=f(1)*2
→f(1)=1
public static void main(String[] args) {
//目标:计算n的阶乘
System.out.println(f(5));//5的阶乘:120
}
public static int f(int n){
if(n==1){
return 1;
}else{
return n*f(n-1);
}
}

递归算法的三要素
- 递归的公式
- 递归的终结点
- 递归的方向必须走向终结点
2.2.2-案例·递归求1~n的和
需求
- 计算1~n的和的结果,使用递归思想解决。
分析
- 假如我们认为存在一个公式f(n)=1+2+3+4+5+...+(n-1)+n
- 那么等价形式公式就是:f(n)=f(n-1)+n
- 递归的终结点:f(1)=1
public static int f2(int n2){
if(n2==1){
return 1;
}else {
return n2+f2(n2-1);
}
}

2.2.3-经典面试题:猴子吃桃问题
需求
- 猴子第一天摘下若干桃子,当即吃了一半,觉得不过瘾,于是又多吃了一个。第二天又吃了前一天剩余桃子的一半,觉得不过瘾,于是多吃了一个,以后每天都吃前一天剩余桃子数量的一半,觉得不过瘾,多吃了一个,等到第十天发现桃子只剩一个了。
- 现在问:猴子第一天摘了多少个桃子?
分析
- 公式:f(n+1)=f(n)-f(n)/2-1
变形
→2f(n+1)=f(n)-2
→f(n)=2f(n+1)+2
终结点
- f(10)=1
public static void main(String[] args) {
System.out.println(f(1));
System.out.println(f(2));
System.out.println(f(3));
}
public static int f(int day){
if(day==10){
return 1;
}else {
return 2*f(day+1)+2;
}
}

2.3-小案例:文件搜索
需求
从D:盘中找到“QQ.exe”这个文件,找到后直接输出其位置
分析
先找出D盘下的所有一级文件对象
判断全部一级文件对象,判断是否是文件
如果是文件,判断是否是自己想要的文件
如果是文件夹,需要继续进入到该文件夹,重复上述步骤。
代码
package com.xunshan.demo2recursion;
import java.io.File;
public class FileSearchDemo4 {
public static void main(String[] args) {
//目标:完成文件搜索,找出D盘下的QQ.exe位置
File dir=new File("D:/");
searchFile(dir,"QQ.exe");
}
public static void searchFile(File dir,String fileName) {
//1.判断极端情况
if (dir==null||!dir.exists()||dir.isFile()) {
return;//不搜索
}
//2.获取当前目录下的所有一级文件或文件夹对象。
File[] files = dir.listFiles();
//3.判断当前目录下是否存在一级文件对象,存在才可以遍历
if (files!=null&&files.length>0) {
//4.遍历一级文件对象
for (File file : files){
//5.判断当前文件对象是否是目标文件
if (file.isFile()) {
//6.是文件,判断文件名是否是目标文件名
if (file.getName().equals(fileName)) {
System.out.println(file.getAbsolutePath());
return;//找到目标文件,直接返回
}
}else {
//7.当前文件对象是文件夹,递归调用
searchFile(file,fileName);
}
}
}
}
}
3-字符集
3.1-常见字符集介绍
标准ASCII编码→码点→二进制(使用一个字节存储)
标准ADCII字符集
- ASCII:美国信息交换标准代码,包含了英文、符号等
- 标准ASCII使用1个字节存储一个字符,首位是0,因此,总共可以表示128个字符,对美国佬来说完全够用。
GBK(汉字内码扩展规范,国标)
- 汉字编码字符集,包含了两万多个汉字等字符,GBK中一个中文字符编码成两个字节的形式存储
- GBK兼容了ASCII字符集
那这个时候就出现了一个问题,如果有人问“我a你”,这个怎么存储呢?
因为汉字是两个字节,a是一个字节,所以GBK字符集做出了规定,汉字的第一个字节的第一位必须是1。
Unicode字符集(统一码,也叫万国码)
- Unicode是国际组织制定的,可以容纳世界上所有文字,符号的字符集。
- UTF-32 每四个字节表示一个字符 42个亿个字符 有容乃大 但是占存储空间大,通信效率变低。
UTF-8这个时候就站出来了,我们所使用的就是UTF-8
UTF-8字符集
- 是Unicode字符集的一种编码方案,采取可变长编码方案,共分四个长度区:1个字节,2个字节,3个字节,4个字节。
- 英文字符、数字等只占1个字节(兼容标准ASCII编码),汉字字符占3个字节。
那么编码方案是这样的
一字节区:0开头 二字节区:110、10开头 三字节区:1110、10、10 四字节区:11110、10、10、10
这个就叫前缀码。
举个例子:a我m
|
a |
97 |
01100001 |
|
我 |
25105 |
110 001000 010001 |
|
m |
109 |
01101101 |
注意
- 字符编码时使用的字符集和解码时使用的字符集必须一致,否则会出现乱码。
- 英文、数字一般不会乱码,因为很多字符集都兼容了ASCII编码。
3.2-字符集的编码、解码操作
对字符的编码(平台默认UTF-8编码)

对字符的解码(指定GBK编码,GBK解码)

4-IO流
4.1-认识IO流
- I指的是Input,称为输入流:负责把数据读到内存中去
- O指的是Output,称为输出流:负责写数据出去

4.1.1-IO流的常见应用场景
- 比如在记事本记录文件
- 玩游戏(游戏的最高分)
- 文件的复制拷贝
- 网络上聊天信息的发送接收都是IO流的读写...
4.1.2-IO流的分类
按照流方向:IO流分为
- 输入流
- 输出流
按照流的内容:IO流分为
- 字节流:适合操作所有类型的文件
比如音频、视频、图片、文本文件的复制,转移等
- 字符流:只适合操作纯文本文件
比如读写txt、java文件等
IO流的体系
抽象类→实现类→对象
- 字节输入流InputStream→FileInputStream
- 字节输出流OutputStream→FileOutputStream
- 字符输入流Reader→FileReader
- 字符输出流Writer→FileWrite
4.2-字节流
4.2.1-FileInputStream(文件字节输入流)
- 作用:以内存为基准,可以把磁盘文件中的数据以字节的形式读入到内存中去。
public static void main(String[] args) throws Exception {
//目标:掌握文件字节输入流读取文件中的字节数组到内存中来。
//1.创建文件字节输入流管道与源文件接通。
// InputStream is=new FileInputStream(new File("day03-file-io\\src\\xunshan02.txt"));
InputStream is=new FileInputStream("day03-file-io\\src\\xunshan02.txt");//简化写法
}

我们接下来看一下怎么读,我们先写了一个愚蠢的代码作为引子。
然后我们看一下正常的我们通过字节数组读是怎么写的。
public static void main(String[] args) throws Exception {
//目标:掌握文件字节输入流读取文件中的字节数组到内存中来。
//1.创建文件字节输入流管道与源文件接通。
// InputStream is=new FileInputStream(new File("day03-file-io\\src\\xunshan02.txt"));
InputStream is=new FileInputStream("day03-file-io\\src\\xunshan03.txt");//简化写法
//2.开始读取文件中的字节并输出:每次读多个字节
//定义一个字节数组用于每次读取字节数组
byte[] buffer=new byte[3];
//定义一个变量,统计每次读取了多少个字节
int count;
while((count=is.read(buffer))!=-1){
//3.把读取的字节数组转换成字符串进行输出。
String str=new String(buffer,0,count);
System.out.println(str);
}
}

拓展
- 每次读取多个字节,性能得到提升,因为每次读取多个字节,可以减少硬盘和内存的交互次数,从而提升效率,但是依然无法避免读取汉字出现输出乱码的问题,存在截断汉字字节的可能性。
注意事项
- 使用FileInputStream每次读取一个字节,读取性能较差,并且读取汉字输出会乱码。
- 使用FileInputStream每次读取多个字节,读取性能得到了提升,但读取汉字输出还是会乱码。
问题:使用字节流读取中文,如何保证输出不乱码?如何解决?
- 定义一个与文件一样大的字节数组,一次性读取完文件的全部字节,java也提供了readAll解决方案。(如果文件过大,创建的字节数组也会过大,可能引起内存溢出)

- 读取文本适合用字符流;字节流适合做数据的转移,比如文件复制。
4.2.2-FileOutputStream(文件字节输出流)
public static void main(String[] args) throws Exception {
//目标:学会使用文件字节输出流。
//1.创建文件字节输出流管道与目标文件接通
OutputStream outputStream = new FileOutputStream("day03-file-io/src/xunshan05.txt", true);//这个true是追加数据,而不是完全覆盖重写。
//2.写入数据到文件中
outputStream.write(97);
outputStream.write('雷'); //会乱码
outputStream.write('b');
outputStream.write("\r\n".getBytes());
//3.写一个字节数组出去
byte[] buffer = "我爱你中国".getBytes();
outputStream.write(buffer);
outputStream.write("\r\n".getBytes());
//4.写一个字节数组的一部分出去
outputStream.write(buffer,0,3);
outputStream.write("\r\n".getBytes());
outputStream.close();//关闭管道 释放资源
}

4.2.3-文件复制
- 任何文件的底层都是字节,字节流做复制,是一字不漏的转移完全部字节,只要复制后的文件格式一致就没问题。

public static void main(String[] args) {
//目标:使用字节流完成文件的复制操作。
//源文件:F:\img\7.jpg
//目标文件:E:\copydemo\img7.jpg(复制过去必须带文件名,无法自动生成文件名)
try {
copyFile("F:\\img\\7.jpg","E:\\copydemo\\img7.jpg");
} catch (Exception e) {
e.printStackTrace();
}
}
//复制文件
public static void copyFile(String srcPath,String destPath) throws Exception {
//1.创建一个字节输入流管道与源文件接通
FileInputStream fis =new FileInputStream(srcPath);
FileOutputStream fos = new FileOutputStream(destPath);
//2.读取一个字节数组,写入一个字节数组 1024+1024+3
byte[] buffer=new byte[1024];
int count;
while((count=fis.read(buffer))!=-1){
fos.write(buffer,0,count);//读取多少字节就写入多少字节
}
System.out.println("复制完毕");
}

4.2.4-关闭资源的方式
try-catch-finally
- finally代码区的特点:无论try中的程序是正常执行了,还是出现了异常,最后都一定会执行finally区,除非JVM终止。
- 作用:一般用于在程序执行完成后进行资源的释放操作(专业级做法)
public static void copyFile(String srcPath,String destPath) {
FileOutputStream fos=null;
FileInputStream fis=null;
try {
//1.创建一个字节输入流管道与源文件接通
fis =new FileInputStream(srcPath);
fos = new FileOutputStream(destPath);
//2.读取一个字节数组,写入一个字节数组 1024+1024+3
byte[] buffer=new byte[1024];
int count;
while((count=fis.read(buffer))!=-1){
fos.write(buffer,0,count);//读取多少字节就写入多少字节
}
System.out.println("复制完毕");
} catch (IOException e) {
e.printStackTrace();
}finally {
//最后一定会执行一次,即便程序出现异常!
try {
if(fos != null)fos.close();
if (fos != null)fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

上面这个代码的执行方案虽然很完美,但是两次try-catch非常冗余。
所以JDK7开始提供了更简单的资源释放方案try-with-resource。
try-with-resource
public static void copyFile(String srcPath,String destPath) {
try (
//1.创建一个字节输入流管道与源文件接通
FileInputStream fis =new FileInputStream(srcPath);
FileOutputStream fos = new FileOutputStream(destPath);
){
//2.读取一个字节数组,写入一个字节数组 1024+1024+3
byte[] buffer=new byte[1024];
int count;
while((count=fis.read(buffer))!=-1){
fos.write(buffer,0,count);//读取多少字节就写入多少字节
}
System.out.println("复制完毕");
} catch (IOException e) {
e.printStackTrace();
}
}

4.3-字符流
4.3.1FileReader文件字符输入流
- 作用:以内存为基准,可以把文件中的数据以字符的形式读入到内存中去。
public static void main(String[] args) {
//目标:掌握文件字符输入流读取字符内容到内存中来。
try (
//1.创建文件字符输入流管道与源文件接通。
Reader fr = new FileReader("day03-file-io\\src\\xunshan06.txt")
) {
//2.定义一个字符数组,每次读取多个字符。
char[] buffer=new char[3];
int count;//统计每次读取的字符个数。
while((count=fr.read(buffer))!=-1){
//3.把读取的字符数组转换成字符串进行输出。
String str=new String(buffer,0,count);
System.out.println(str);
}
//拓展:文件字符输入流一次读取多个字符,性能较好,而且读取中文
//是按照字符读取,不会出现乱码,这是一种读取中文很好的方案。
}catch (Exception e){
e.printStackTrace();
}
}

4.3.2FileWriter文件字符输出流
- 作用:以内存为基准,把内存中的数据以字符的形式写出到文件中去。
- 和输入流一样,FileWriter作为Java语言也提供了构造器和其内部的方法。
//目标:搞清楚文件字符输出流的使用,写字符出去的流。
//1.创建一个文件字符输出流管道与源文件接通。
try (
//1.创建文件字符输出流管道与源文件接通。
FileWriter fw = new java.io.FileWriter("day03-file-io\\src\\xunshan07.txt")
) {
//2.写出数据
fw.write('a');
fw.write("\r\n");
fw.write("hello");//3.写多个字符出去。
fw.write("\r\n");
fw.write("java",1,2);//3.写字符串的一部分出去。
fw.write("\r\n");
char[] buffer=new char[]{'a','b','c','d','e'};//4.写一个字符数组出去。
fw.write(buffer);
fw.write(buffer,1,2);//5.写一个字符数组的一部分出去。
}catch (Exception e){
e.printStackTrace();
}

以上方法是覆盖,我们也可以追加数据而不是把原文件数据覆盖。

字符输出流的注意实现
- 字符流输出流写出数据后,必须刷新流,或者关闭流,写出去的数据才能生效。
fw.flush()
//刷新后,流可以继续使用
fw.close()
//关闭包含了刷新,但是关闭后流不能继续使用了
4.4-缓冲流
4.4.1-缓冲字节流
BuffedInputStream缓冲字节输入流
BuffedOutputStream缓冲字节输出流
- 作用:可以提高字节输入流数据的性能
- 原理:缓冲字节输入流自带了8KB缓冲池;缓冲字节输出流也自带了8KB缓冲池。

这是BufferdInputStream的部分源码,可以看到自带了8KB的缓冲池,输出流也是同理。
public static void main(String[] args) {
//目标:使用缓冲字节流完成文件的复制操作。
//源文件:F:\img\7.jpg
//目标文件:E:\copydemo\img7.jpg(复制过去必须带文件名,无法自动生成文件名)
try {
copyFile("F:\\img\\7.jpg","E:\\copydemo\\img7.jpg");
} catch (Exception e) {
e.printStackTrace();
}
}
//复制文件
public static void copyFile(String srcPath,String destPath) {
try (
//1.创建一个字节输入流管道与源文件接通
FileInputStream fis =new FileInputStream(srcPath);
//把低级的字节输入流包装成缓冲字节输入流,提高读的效率,默认缓冲区是8kb。
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream(destPath);
//3.把低级的字节输出流包装成缓冲字节输出流,提高写的效率,默认缓冲区是8kb。
BufferedOutputStream bos = new BufferedOutputStream(fos);
){
//2.读取一个字节数组,写入一个字节数组 1024+1024+3
byte[] buffer=new byte[1024];
int count;
while((count=bis.read(buffer))!=-1){
bos.write(buffer,0,count);//读取多少字节就写入多少字节
}
System.out.println("复制完毕");
} catch (IOException e) {
e.printStackTrace();
}
}
我们的使用,只需要用Bufferd包一下就可以了。
4.4.2-缓冲字符流
BuffedReader缓冲字符输入流
- 作用:可以提高字符输入流数据的性能
- 原理:缓冲字符输入流自带了8KB缓冲池;缓冲字符输出流也自带了8KB缓冲池。
字符缓冲输入流新增的功能:按照行读取字符
public static void main(String[] args) {
//目标:搞清楚缓冲字符输入流读取字符内容:性能提升了,多了按行读取文本的内容。
try (
//1.创建文件字符输入流管道与源文件接通。
Reader fr = new FileReader("day03-file-io\\src\\xunshan06.txt");
//把低级的流包装成缓冲字符输入流管道
BufferedReader br = new BufferedReader(fr)
) {
//2.定义一个字符串变量存储读取的一行内容。
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}

- 目前读取文本最优雅的方案;性能好,不乱码,可以按行读取。
BuffedWriter缓冲字符输出流
- 作用:可以提高字符输出流数据的性能
- 原理:缓冲字符输入流自带了8KB缓冲池;缓冲字符输出流也自带了8KB缓冲池。
字符缓冲输出流新增的功能:换行
public static void main(String[] args) {
// 目标:搞清楚缓冲字符输出流的使用,提高了字符输出流写字符的效率,多了换行的功能。
// 1. 创建一个文件字符输出流管道与源文件接通。
try (
// 1. 创建文件字符输出流管道与源文件接通。
Writer fw = new FileWriter("day03-file-io\\src\\xunshan07.txt", true);
// 2. 创建一个缓冲字符输出流管道与源文件接通。
BufferedWriter bw = new BufferedWriter(fw);
) {
// 2. 写出数据
bw.write('a');
bw.newLine(); // 使用 newLine() 方法换行
// 3. 写多个字符出去。
bw.write("hello");
bw.newLine();
// 4. 写字符串的一部分出去。
bw.write("java", 1, 2);
bw.newLine();
// 5. 写一个字符数组出去。
char[] buffer = new char[]{'a', 'b', 'c', 'd', 'e'};
bw.write(buffer);
bw.newLine();
// 6. 写一个字符数组的一部分出去。
bw.write(buffer, 1, 2);
} catch (IOException e) {
e.printStackTrace();
}
}
4.5-其他流
4.5.1-InputStreamReader(字符输入转换流)
- 解决不同编码时,字符流读取文本内容乱码的问题。
- 解决思路:先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流中的字符也就不乱码了。

- 那么我们现在用字符输入转换流解决这个问题。
//目标:使用字符输入转换流解决问题:不同编码读取乱码
//代码:UTF-8 文件UTF-8 读取不乱码
//代码:UTF-8 文件GBK 读取乱码
try (
//先提取文件的原始字节流
InputStream is=new FileInputStream("day03-file-io\\src\\xunshan09.txt");
//指定编码把原始字节流转换成字符输入流
InputStreamReader isr=new InputStreamReader(is,"GBK");
//把低级的流包装成缓冲字符输入流管道
BufferedReader br = new BufferedReader(isr)
) {
//2.定义一个字符串变量存储读取的一行内容。
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}

4.5.2-PrintStream/PrintWriter打印流
- 作用:打印流可以实现更方便、更高效的打印数据出去,能实现打印啥出去就是啥出去。(我们可能打印97出去变成了‘a’,但是使用打印流97就是97)
public static void main(String[] args) {
//目标:认识PrintStream打印流的常用方法。
try (PrintStream ps = new PrintStream("day03-file-io/src/ps.txt")) {
ps.print("hello");
ps.println("hello");
ps.println(true);
ps.println(100);
ps.println(100.5);
ps.println('a');
ps.println(new String[]{"a","b","c"});
ps.println(new int[]{1,2,3,4,5});
ps.println(new Object());
}catch (Exception e){
e.printStackTrace();
}
}

PrintStream/PrintWriter的使用方法完全一样,如果想要追加可以写一个低级流,然后加上true之后用打印流包装一下。
4.5.3-DataInputStream/DataOutputStream(特殊数据输出/输入流)
- 允许把数据和其类型一并写出去。
因为输入输出两个代码的区别只有Input和Output的差别,所以我们只罗列一个。
public static void main(String[] args) {
//目标:认识特殊数据流的使用。
try (DataInputStream dis = new DataInputStream(new FileInputStream("day03-file-io/src/data.txt"))) {
System.out.println(dis.readInt());
System.out.println(dis.readUTF());
System.out.println(dis.readBoolean());
System.out.println(dis.readDouble());
System.out.println(dis.readChar());
}catch (Exception e){
e.printStackTrace();
}
}

4.6-IO框架
我们用IO框架,对于前面各种流动辄好几行的代码,大部分都能直接简化成一行,但是我们学前面的内容也是有意义的,它可以打好我们的基本功,让我们无论是调用IO框架还是解读别人的源码,都知道是怎么来的。
什么是框架?
- 框架(Framework)是一个预先写好的代码库或一组工具,旨在简化和加速开发过程。
- 框架的形式:一般是把类、接口等编译成class形式,再压缩成一个.jar结尾的文件发行出去。
什么是IO框架
- 封装了java提供的对文件、数据进行操作的代码,对外提供了更简单的方式来对文件进行操作,对数据进行读写等。
导入commons-ios-2.11.0.jar

- 在项目中创建一个文件夹:lib
- 将commons-ios.jar文件复制到lib文件夹
- 在jar文件上右键,选择Add as Library→点击OK
- 在类中导包使用
Commons-io框架
Commons-io是apache开源基金组织提供的一组有关IO操作的小框架,目的是提高IO流的开发效率

public static void main(String[] args) throws IOException {
//目标:用框架封装的IO流,完成文件的复制。
//1、把文件复制到指定的目录下。
FileUtils.copyFile(new File("F:\\img\\7.jpg"),new File("E:\\copydemo\\img7.jpg"));
//2.删除文件
FileUtils.forceDelete(new File("E:\\copydemo\\img7.jpg"));
}
因为诸多功能的用法有了前文的基础,都是一看就懂的,所以我们在这里就只演示一个复制和一个删除操作。

能看到这里真的很不容易,这应该也是博主目前写过最长的一个博客,感谢大家的观看。

3827

被折叠的 条评论
为什么被折叠?



