目录
异常概述
什么是异常?
即非正常情况,通俗地说,异常就是程序出现的错误
异常的分类(Throwable)
异常(Exception)
合理的应用程序可能需要捕获的问题 举例:NullPointerException
错误(Error)
合理的应用程序不应该试图捕获的问题 举例:StackOverFlowError 异常的处理方式
JVM默认的异常处理方式
在控制台打印错误信息,并终止程序
开发中异常的处理方式
try…catch(finally):捕获,自己处理
try {
// 尝试执行的代码
} catch(Exception e) {
// 出现可能的异常之后的处理代码
} finally {
// 一定会执行的代码,如关闭资源
}
package com.itcast.demo11;
public class Test {
public static void main(String[] args) {
try {
int a = 10/10;
System.out.println(a);
}catch (Exception e){
System.out.println("被除数不能为0");
}finally {
System.out.println("加不加都一样");
}
System.out.println("这句话执行了吗");
}
}
throws:抛出,交给调用者处理
public void 方法名() throws Exceptoin {
}
package com.itcast.demo11;
public class Test1 {
public static void main(String[] args) throws Exception {
//show()方法把异常抛出了,调用者需要处理
//1.接着抛异常
// show();
// System.out.println("执行了吗");
//2.try.catch处理
try {
show();
} catch (Exception e) {
System.out.println("代码出问题了");
}
System.out.println("执行了吗");
}
public static void show() throws Exception {
int a = 10 / 0;
System.out.println(a);
}
}
异常处理的注意事项
多个异常分别处理:
try {
// 尝试执行的代码
} catch(异常A e) {
// 出现可能的异常之后的处理代码
} catch(异常B e) {
// 出现可能的异常之后的处理代码
} finally {
// 一定会执行的代码,如关闭资源
}
finally代码块:
可以省略(不能和catch部分同时省略) finally代码之前若有return语句,先执行return语句,再执行finally代码 块,最后返回return的结果
方法重写:
子类方法不能比父类方法抛出更大的异常
IO流概述
什么是IO流?
I/O,即输入(Input)输出(Output),IO流指的是数据像连绵的流体一样进行传输。
IO流能干什么?
在本地磁盘或网络上传输(读/写)数据
IO流的分类
按数据流向分:
输入流
输出流
按操作方式分:
字节流:
- InputStream
- OutputStream
字符流:
- Reader
- Writer
IO流体系
字符流:按字符读写数据的IO流
Reader
- FileReader(普通)
- BufferedFileReader(高效)
Writer
- FileWriter(普通)
- BufferedFileReader(高效)
字节流:按字节读写数据的IO流
InputStream
- FileInputStream(普通)
- BufferedInputStream(高效)
OutputStream
- FileOutputStream(普通)
- BufferedOutputStream(高效)
File类
概念
文件,文件夹,一个File对象代表磁盘上的某个文件或文件夹
构造方法:
File(String pathname)
File(String parent, String child)
File(File parent, String child)
成员方法:
createNewFile():创建文件
mkdir()和mkdirs():创建目录
isDirectory():判断File对象是否为目录
isFile():判断File对象是否为文件
exists():判断File对象是否存在
package com.itcast.demo11;
import java.io.File;
import java.io.IOException;
public class Test2 {
public static void main(String[] args) throws IOException {
//方式一 根据字符串形式的路径获取File对象
File file1 = new File("D:\\2021.3.1\\java\\1.txt");
System.out.println("file1:" + file1);
//方式二 根据字符串形式的父目录以及子目录创建File对象
File file2 = new File("D:\\2021.3.1\\java", "1.txt");
System.out.println("file2:" + file2);
//方式三 根据父目录对象,以及字符串形式的子目录来获取File对象
File file3 = new File("D:\\2021.3.1\\java");
File file4 = new File(file3, "1.txt");
System.out.println("file4:" + file4);
//创建功能
File file5 = new File("D:\\2021.3.1\\java\\2.txt");
boolean flag1 = file5.createNewFile();
System.out.println(flag1);
//创建文件夹
File file6 = new File("D:\\2021.3.1\\java\\a");
boolean flag2 = file6.mkdir();
System.out.println(flag2);
//多级目录
File file7 = new File("D:\\2021.3.1\\java\\a\\b\\c");
boolean flag3 = file7.mkdirs();
System.out.println(flag3);
//判断功能
File file8 = new File("D:\\2021.3.1\\java\\a\\b");
System.out.println("测试file8是否为文件夹:" + file8.isDirectory());
System.out.println("测试file8是否为文件:" + file8.isFile());
System.out.println("测试file8是否存在:" + file8.exists());
}
}
getAbsolutePath():获取文件的绝对路径
从本地磁盘开始的路径
举例:C:\Users\itcast\Desktop
getPath():获取文件的相对路径
相对某一位置的路径
Java项目中,相对路径从项目名开始
getName():获取文件名
list():获取指定目录下所有文件(夹)名称数组
listFiles():获取指定目录下所有文件(夹)File数组
package com.itcast.demo11;
import java.io.File;
public class Test3 {
public static void main(String[] args) {
File file1 = new File("lib/1.txt");
//绝对路径
String path1 = file1.getAbsolutePath();
System.out.println(path1);
//相对路径
String path2 = file1.getPath();
System.out.println(path2);
//获取文件名
String file1Name = file1.getName();
System.out.println(file1Name);
//获取lib文件夹下所有的文件,文件夹,名称数组String[]
File file2 = new File("lib");
String[] list = file2.list();
for (String name : list) {
System.out.println(name);
}
File[] files = file2.listFiles();
for (File file : files) {
System.out.println(file);
}
}
}
字符流读写文件
字符流读数据 – 按单个字符读取
创建字符流读文件对象:
Reader reader = new FileReader("readme.txt");
调用方法读取数据:
int data = reader.read();
读取一个字符,返回该字符代表的整数,若到达流的末尾,返回-1
异常处理:
throws IOException
package com.itcast.demo11;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class Test4 {
public static void main(String[] args) throws IOException {
//创建字符输入流对象
Reader reader = new FileReader("lib/1.txt");
//读取数据
// int ch1 = reader.read();
// System.out.println(ch1);
// int ch2 = reader.read();
// System.out.println(ch2);
// int ch3 = reader.read();
// System.out.println(ch3);
// int ch4 = reader.read();
// System.out.println(ch4);
//优化
int ch; //接受读取到的字符
/*
(ch = reader.read()) != -1
1.执行reader.read()读取一个字符
2.将读取到的字符赋值给变量
3.用读取到的字符与-1比较
*/
while ((ch = reader.read()) != -1) {
//ch = reader.read();
System.out.println(ch);
}
//释放资源
reader.close();
}
}
字符流读数据 – 按字符数组读取
创建字符流读文件对象:
Reader reader = new FileReader("readme.txt");
调用方法读取数据:
// 读取字符到数组中,返回读取的字符数,若到达流的末尾,返回-1
char[] chs = new char[2048];
int len = r.read(chs);
异常处理:
throws IOException
package com.itcast.demo11;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class Test5 {
public static void main(String[] args) throws IOException {
Reader reader = new FileReader("lib/2.txt");
// char[] chs = new char[3];
// int len1 = reader.read(chs);
// System.out.println(chs); //abc
// System.out.println(len1); //3
//
// int len2 = reader.read(chs);
// System.out.println(chs); //def
// System.out.println(len2); //3
//
// int len3 = reader.read(chs);
// System.out.println(chs); //gef
// System.out.println(len3); //1
//
// int len4 = reader.read(chs);
// System.out.println(chs); //gef
// System.out.println(len4); //-1
//优化
char[] chars = new char[3];
int len;
while ((len = reader.read(chars)) != -1) {
//chars:要操作的数组 0:起始索引 len:要操作字符的个数
String s = new String(chars, 0, len);
System.out.println(s);
}
reader.close();
}
}
字符流写数据 – 按单个字符写入
创建字符流写文件对象:
Writer writer = new FileWriter("dest.txt");
调用方法写入数据:
int x = '中';
writer.write(x); // 写一个字符
异常处理:
throws IOException
字符流写数据 – 按字符数组写入
创建字符流写文件对象:
Writer writer = new FileWriter("dest.txt");
调用方法写入数据(写入字符数组):
char[] chs = {'橙', '心', '橙', '意'};
writer.write(chs); // 写一个字符数组
异常处理:
throws IOException
字符流写数据 – 按字符数组写入
创建字符流写文件对象:
Writer writer = new FileWriter("dest.txt");
调用方法写入数据(写入字符串):
writer.write("小黑爱学习"); // 写入一个字符串
异常处理:
throws IOException
package com.itcast.demo11;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class Test6 {
public static void main(String[] args) throws IOException {
//创建字符输出流
Writer writer = new FileWriter("lib/1.txt");
//一次写一个字符
writer.write("ok");
//一次写一个指定的字符数组
char[] chars = {'今', '天', '星', '期', '一'};
writer.write(chars, 2, 3);
//一次写一个字符串
writer.write("今天开心");
writer.close();
}
}
字符流拷贝文件 – 按单个字符读写
创建字符流读文件对象:
Reader reader = new FileReader("readme.txt");
创建字符流写文件对象:
Writer writer = new FileWriter("dest.txt");
调用方法读取数据:
int data = reader.read();
调用方法写入数据:
writer.write(data);
异常处理:
throws IOException
关闭资源:
finally {
reader.close();
writer.close();
}
package com.itcast.demo11;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyFile {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("lib/1.txt");
FileWriter fw = new FileWriter("lib/2.txt");
int len;
while ((len = fr.read()) != -1) {
fw.write(len);
}
fr.close();
fw.close();
}
}
字符流拷贝文件 – 按字符数组读写
创建字符流读文件对象:
Reader reader = new FileReader("readme.txt");
创建字符流写文件对象:
Writer writer = new FileWriter("dest.txt");
调用方法读取数据:
char[] chs = new char[2048];
int len = reader.read(chs);
调用方法写入数据:
writer.write(chs, 0, len)
异常处理:
throws IOException
关闭资源:
finally {
reader.close();
writer.close();
}
package com.itcast.demo11;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyFile1 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("lib/1.txt");
FileWriter fw = new FileWriter("lib/2.txt");
char[] chars = new char[2048];
int len; //读取到的有效字符
while ((len = fr.read(chars)) != -1) {
fw.write(chars, 0, len);
}
fr.close();
fw.close();
}
}
在实际生产环境中,流的操作非常的缓慢、耗时(打开资源、操作资源、关闭资源),所以,实际生产环境中的流操作对效率的要求很高。为此,Java的设计者们提供了高效的缓冲流供开发者使 用。
字符缓冲流拷贝文件的标准代码
创建字符流读文件对象:
BufferedReader br = new BufferedReader(new FileReader("readme.txt"));
创建字符流写文件对象:
BufferedWriter bw = new BufferedWriter(new FileWriter("dest.txt"));
异常处理:
throws IOException
使用while循环读写数据:
char[] chs = new char[2048];
int len;
while((len = br.read(chs)) != -1) {
bw.write(chs, 0, len);
}
关闭资源:
br.close();
bw.close();
字符缓冲流普通用法
package com.itcast.demo11;
import java.io.*;
import java.nio.channels.NonReadableChannelException;
public class CopyFile2 {
public static void main(String[] args) throws IOException {
//字符缓冲自带有缓冲区,大小为8192个字符,16KB
//创建字符缓冲输入流对象,关联目的地文件
FileReader fr = new FileReader("lib/1.txt");
BufferedReader br = new BufferedReader(fr);
//简化
BufferedReader br2 = new BufferedReader(new FileReader("lib/1.txt"));
FileWriter fw = new FileWriter("lib/2.txt");
BufferedWriter bw = new BufferedWriter(fw);
//简化
BufferedWriter bw2 = new BufferedWriter(new FileWriter("lib/2.txt"));
int len;
while ((len = br.read()) != -1) {
bw.write(len);
}
br.close();
bw.close();
}
}
字符缓冲流一次读写一行
package com.itcast.demo11;
import java.io.*;
import java.nio.channels.NonReadableChannelException;
public class CopyFile2 {
public static void main(String[] args) throws IOException {
//字符缓冲自带有缓冲区,大小为8192个字符,16KB
//创建字符缓冲输入流对象,关联目的地文件
BufferedReader br = new BufferedReader(new FileReader("lib/1.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("lib/2.txt"));
String str;
while ((str = br.readLine()) != null) {
bw.write(str);
//换行
bw.newLine();
}
br.close();
bw.close();
}
}
字符流只能拷贝纯文本文件。
字节流读写文件
字节流拷贝文件 – 按单个字节读写
创建字节流读文件对象:
InputStream is = new FileInputStream("Desktop.jpg");
创建字节流写文件对象:
OutputStream os = new FileOutputStream("D:\\桌面.jpg");
异常处理:
throws IOException
使用while循环读写数据:
int b;
while((b = is.read()) != -1) {
os.write(b);
}
关闭资源:
is.close();
os.close();
package com.itcast.demo11;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyFile3 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("lib/a.jpg");
FileOutputStream fos = new FileOutputStream("lib/b.jpg");
int len;
while ((len = fis.read()) != -1) {
fos.write(len);
}
fis.close();
fos.close();
}
}
字节流拷贝文件 – 按字节数组读写
创建字节流读文件对象:
InputStream is = new FileInputStream("Desktop.jpg");
创建字节流写文件对象:
OutputStream os = new FileOutputStream("D:\\桌面.jpg");
异常处理:
throws IOException
定义字节数组,每次读取2048个字节:
byte[] b = new byte[2048];
使用while循环读写数据:
int len;
while((len = is.read(b)) != -1) {
os.write(b, 0, len);
}
关闭资源:
is.close();
os.close();
package com.itcast.demo11;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyFile3 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("lib/a.jpg");
FileOutputStream fos = new FileOutputStream("lib/b.jpg");
//定义变量,用来接收读取到的内容
byte[] bys = new byte[1024];
//读取到的有效字节数
int len;
while ((len = fis.read(bys)) != -1) {
fos.write(bys, 0, len);
}
fis.close();
fos.close();
}
}
字节缓冲流拷贝文件的标准代码
创建字节缓冲流读文件对象:
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("jdk-11.0.1_doc-all.zip"));
创建字节缓冲流写文件对象:
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\jdk-11.0.1_doc-all.zip"));
异常处理:
throws IOException
定义字节数组,每次读取2048个字节:
byte[] bs = new byte[2048];
使用while循环读写数据:
int len;
while((len = bis.read(bs)) != -1) {
bos.write(bs, 0, len);
}
关闭资源:
bis.close();
bos.close();
package com.itcast.demo11;
import org.omg.CORBA.NO_IMPLEMENT;
import java.io.*;
public class CopyFile3 {
public static void main(String[] args) throws IOException {
// FileInputStream fis = new FileInputStream("lib/a.jpg");
// BufferedInputStream bis = new BufferedInputStream(fis);
//简化
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("lib/a.jpg"));
//FileOutputStream fos = new FileOutputStream("lib/b.jpg");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("lib/b.jpg"));
//定义变量,用来接收读取到的内容
int len;
while ((len = bis.read()) != -1) {
bos.write(len);
}
bis.close();
bos.close();
}
}
案例:模拟文件上传功能
需求:使用控制台模拟实际开发中上传用户头像的功能
完整代码
package com.itcast.demo11;
import java.io.*;
import java.util.Scanner;
public class UploadFile {
public static void main(String[] args) throws IOException {
File path = getPath();
System.out.println(path);
boolean flag = isExists(path.getName());
if (flag) {
//如果存在,提示用户头像已存在,上传失败
System.out.println("用户头像已存在,上传失败");
} else {
//如果不存在,就上传用户头像,并提示上传成功
upLoadFile(path);
}
}
//获取要上传的用户头像路径 getPath()
public static File getPath() {
//提示用户录入头像路径,并接收
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请录入您要上传的用户头像路径");
String path = sc.nextLine();
//判断路径名(jpg,png,bmp)
//不是就提示:您录入的不是图片,请重新输入
if (!path.endsWith(".jpg") && !path.endsWith(".png") && !path.endsWith(".bmp")) {
System.out.println("您录入的不是图片,请重新录入");
continue;
}
//是,程序继续执行,判断路径是否存在,并且是否是文件
File file = new File(path);
if (file.exists() && file.isFile()) {
return file;
} else {
//如果不是就提示路径不合法
System.out.println("您录入的路径不合法,请重新录入");
}
//如果是,直接返回
}
}
//定义一个方法,用来判断要上传的用户头像,在lib文件夹中是否存在
public static boolean isExists(String path) {
//将lib文件封装成File对象
File file = new File("lib");
//获取lib文件夹中所有的文件(夹)的名称数组
String[] names = file.list();
//遍历第二步获取到的数组,用获取到的数据依次和path进行比较
for (String name : names) {
if (name.equals(path)) {
//如果一致,说明该用户头像已经存在了,就返回true
return true;
}
}
//如果不一致,说明该用户头像不存在,就返回false
return false;
}
//定义方法,用来上传具体用户头像 path:数据源文件路径
public static void upLoadFile(File path) throws IOException {
//创建字节输入流,关联数据源文件
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(path));
//创建字节输出流,关联目的地文件
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("lib/" + path.getName()));
//定义变量,记录读取到的数据
int len;
//循环读取,只要条件满足就一直读,并将读取到的数据赋值给变量
while ((len = bis.read()) != -1) {
//将读取到的数据写入到目的地文件中
bos.write(len);
}
//释放资源
bis.close();
bos.close();
System.out.println("上传完成!");
}
}