一、异常
(1)就是程序运行过程中,遇到了问题,这就叫异常。
(2)异常的体系
Throwable 其实应该分三种
Error
通常出现重大问题如:服务器宕机数据库崩溃等。
不编写针对代码对其处理。
Exception
除了 RuntimeException 和其所有子类,其他所有的异常类都是在编译的时候必须要处理的
要么try,要么抛
RuntimeException
RuntimeException和其所有的子类,都不会在编译的时候报异常,而是在运行时报异常,这时候我们
就需要回头看看我们的代码是否有问题,比如角标越界,空指针等。
(3)Throwable Runnable
1:getMessage() :返回此 throwable 的详细消息字符串
String detailMessage;
Throwable(){}
Throwable(String message) {
this.detailMessage = message;
}
public String getMessage() {
return detailMessage;
}
}
2:toString():获取异常类名和异常信息,返回字符串。
3:printStackTrace():获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。
(4)处理异常处理方式:
A:try...catch...finally
格式:
try{
需要检测的代码;
}
catch(异常类 变量){
异常处理代码;
}
...
finally{
一定会执行的代码;
}
可以有下面三种搭配形式:
**try...catch(...)
**try...finally
**try...catch(...)...finally
*(final finalize finally三者的区别
* finally最终的
* 一定会执行的代码放在这里
* finally只有一种情况不执行,就是在他之前退出了jvm虚拟机).
public static void main(String[] args) {
//demo1();
int num = getNum();
System.out.println(num);
}
private static void demo1() {
try {
System.out.println(1/0);
} catch (Exception e) {
System.out.println("catch执行了吗");
System.exit(0);
return;
} finally { //关闭流对象,释放资源
System.out.println("finally执行了吗");
}
}
public static int getNum() {
int x = 10;
try {
System.out.println(1/0);
return x;
} catch (Exception e) {
x = 20;
return x; //当程序执行到了return语句会有一个返回路径
}finally { //但是在完全return之前会看有没有finally如果有
//先执行finally,再把return返回路径的值返回
x = 30;
System.out.println("finally执行了吗");
//return x;
}
}
B:抛出 throws throw
throws:用于标识函数暴露出的异常。thorws用在函数上,后面跟异常类名(可以由多个,隔开)。
throw:用于抛出异常对象。throw用在函数内,后面跟异常对象。new Exception();
C:到底用谁?
**你能处理,建议处理。try...catch...finally
**你处理不了,抛出。
**在实际开发中,是分层开发,底层代码是能抛出尽量抛出,用日志记录住异常信息,并提供解决方案
D:自定义异常
自定义类继承Exception或者其子类(RuntimeException)
class MyException extends Exception{
MyException(){}
MyException(String message){
super(message); //将信息传递给父类,调用父类封装好的构造方法
}
}
class Student {
public void giveAge(int age) throws MyException {
if(age>40 || age<16) {
//throw new MyExcetpion("建议不学了");
MyExcepiont my = new MyExcetpion("建议不学了");
throw my;
}
else {
System.out.println("可以学习Java");
}
}
}
E:RuntimeException和Exception
区别:RuntimeException就是要你改代码的。你可以不处理。
二.File
1.什么是File类
File类对象可以代表一个路径, 此路径可以是文件也可以是文件夹, 该类方法可以对这个路径进行各种操作
2.创建对象
给File类构造函数传一个String类型的路径就可以创建对象
路径分为两种: 绝对路径, 相对路径
绝对路径: 从盘符开始, 是一个固定的路径
相对路径: 不从盘符开始, 相对于某个位置. 在Eclipse中的Java工程如果使用相对路径, 那么就相对于工程根目录. cmd则相对应于当前目录.
import java.io.File;
public class Demo1_File {
/**
* @param args
* D:\workspace0803\day20\day20笔记.txt
*/
public static void main(String[] args) {
File file = new File("F:\\2014\\Test3.java");//绝对路径,从盘符开始
System.out.println(file.exists());
File file2 = new File("day20笔记.txt"); //相对路径,相对于java工程的根目录
System.out.println(file1.exists());
}
}
3.常用方法
*****booleanexists() 判断是否存在
booleanisAbsolute(); 是否是绝对路径
*****booleanisDirectory(); 是否是文件夹
*****booleanisFile(); 是否是文件
booleanisHidden(); 是否是隐藏
getAbsolutePath(); 获取绝对路径
getFreeSpace(); 获取当前盘符剩余空间
getTotalSpace(); 获取当前盘符总空间
getUsableSpace(); 获取当前盘符可用空间
*****getParent()); 获取父级路径
*****getName()); 获取文件名
setReadable(false); 设置是否可读
setWritable(false); 设置是否可写
setExecutable(false); 设置是否可执行
canRead(); 是否可读
canWrite(); 是否可写
canExecute(); 是否可执行
setLastModified(); 设置文件的最后修改时间
*****lastModified(); 获取文件的最后修改时间
*****createNewFile() 创建文件
*****mkdir(); 创建文件夹(仅一级)
*****mkdirs(); 创建文件夹(父级不存在也创建)
**renameTo(); 改名, 可以移动文件
*****delete() 删除, 文件可以直接删除, 文件夹只能删空的
*****length() 文件大小
String[]list()
*****File[]listFiles()
4.递归
public class Demo6_Digui {
/**
* @param args
* 递归
* 方法自己调用自己
* 5!
* fun(5)
* 5 * fun(4)
* 4 * fun(3)
* 3 * fun(2)
* 2 * fun(1)
* 弊端:如果调用的次数过多,会出现栈内存溢出
*/
public static void main(String[] args) {
/*int result = 1;
for(int i = 1; i <= 5; i++) {
result = result * i;
}
System.out.println(result);*/
int result = getResult(10000);
System.out.println(result);
}
public static int getResult(int num) {
if(num == 1) {
return 1;
}
return num * getResult(num - 1);
}
}
举例
键盘录入一个文件夹路径
如果录入的文件夹路径不存在,提示重输
如果录入的文件夹路径是文件路径,提示重输
如果录入的是文件夹路径,将其返回
import java.io.File;
import java.util.Scanner;
public class Test1 {
public static void main(String[] args) {
File dir = getDir();
System.out.println(dir);
}
public static File getDir() {
Scanner sc = new Scanner(System.in); //创建Scanner
System.out.println("请输入一个文件夹路径:"); //提示
while(true) {
String line = sc.nextLine(); //将键盘录入的字符串存储在line中
File dir = new File(line); //封装成File对象
if(!dir.exists()) { //如果路径不存在
System.out.println("您录入的文件夹路径不存在,请重新录入一个文件夹路径");//提示
}else if(dir.isFile()) { //如果路径是文件
System.out.println("您录入的是文件路径,请重新输入一个文件夹路径");//提示
}else {
return dir; //将文件夹路径返回
}
}
}
}
三、IO流
1.概念
IO流用来处理设备之间的数据传输
Java对数据的操作是通过流的方式
Java用于操作流的类都在IO包中
流按流向分为两种:输入流,输出流。
流按操作类型分为两种:字节流与字符流。 字节流可以操作任何数据,字符流只能操作纯字符数据,比较方便。
2.IO流常用父类
字节流的抽象父类:
InputStream,OutputStream
字符流的抽象父类:
Reader, Writer
3.IO程序书写
使用前,导入IO包中的类
使用时,进行IO异常处理
使用后,释放资源
二.字节流
1.读取文件
创建FileInputStream对象, 指定一个文件. 文件必须存在, 不存在则会抛出FileNotFoundException
使用read()方法可以从文件中读取一个字节. 如果读取到文件末尾会读到-1
读取结束后需要释放资源, 调用close()方法关闭输入流
2.写出文件
创建FileOutputStream对象, 指定一个文件. 文件不存在会创建新文件, 存在则清空原内容. 如果需要追加, 在构造函数中传入true.
使用write()方法可以向文件写出一个字节.
写出结束后同样需要调用close()
3.拷贝文件
可以从文件中逐个字节读取, 逐个字节写出, 但这样做效率非常低
我们可以定义一个数组作为缓冲区, 一次读取多个字节装入数组, 然后再一次性把数组中的字节写出1byte = 8bit
4.常用方法
InputStream:
read() 读取一个字节
read(byte[]) 读取若干(数组长度)字节
available() 获取可读的字节数
close() 关闭流, 释放资源
OutputStream:
write(int) 写出一个字节
write(byte[]) 写出数组中的所有字节
write(byte[],start,len);
close() 关闭流, 释放资源
5.BufferedInputStream
BufferedInputStream内置了一个缓冲区(数组)
从BufferedInputStream中读取一个字节时
BufferedInputStream会一次性从文件中读取8192个, 存在缓冲区中, 返回给程序一个
程序再次读取时, 就不用找文件了, 直接从缓冲区中获取
直到缓冲区中所有的都被使用过, 才重新从文件中读取8192个
6.BufferedOutputStream
BufferedOutputStream也内置了一个缓冲区(数组)
程序向流中写出字节时, 不会直接写到文件, 先写到缓冲区中
直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件里
*(read()方法每次读取都返回一个字节,为什么用int接收而不用byte接收呢?
因为文件都有结束标记,结束标记都是-1,-1是int类型的,如果结束标记是byte类型的-1,读到文件的中间很有可能遇到11111111.这样文件就会读取终止,剩下读不出来了,所有每次读取返回的都是int,将byte提升为int会在前面补上24个0,byte类型的-1就变成了int类型的255了,这样只有遇到文件的结束标记才会停止读取)
7.种字节读写方式
1)根据文件大小创建字节数组,一次读到字节数组中,一次将字节数组中的内容写出去, 这种拷贝的弊端,有可能内存溢出。
2)一个字节一个读写,效率慢。
3)创建字节数组长度为1024*8,将数据读到字节数组中,从字节数组中写出去,写到文件上,相对于单字节效率快。
4)读一次先将缓冲区读满,再一个一个的返给, 写一次,是先将缓冲区装满,再一起写出,解决溢出,效率快
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo4_Array {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("致青春.mp3"); //创建输入流对象,关联致青春.mp3
FileOutputStream fos = new FileOutputStream("copy.mp3"); //创建输出流对象,关联copy.mp3
byte[] arr = new byte[fis.available()]; //根据文件大小创建字节数组
fis.read(arr); //一次读到字节数组中
fos.write(arr); //一次将字节数组中的内容写出去
fis.close();
fos.close();
//这种拷贝的弊端,有可能内存溢出
}
public static void Demo1 throws IOException {
FileInputStream fis = new FileInputStream("致青春.mp3");
FileOutputStream fos = new FileOutputStream("copy.mp3");
int b;
while((b = fis.read()) != -1) {
fos.write(b);
}
fis.close();
fos.close();
}
private static void demo2() throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream("致青春.mp3"); //创建输入流对象,关联致青春.mp3
FileOutputStream fos = new FileOutputStream("copy.mp3"); //创建输出流对象,关联copy.mp3
byte[] arr = new byte[1024 * 8]; //创建字节数组长度为1024*8
int len;
while((len = fis.read(arr)) != -1) { //将数据读到字节数组中
fos.write(arr,0,len); //从字节数组中写出去,写到文件上
}
fis.close(); //关流,释放资源
fos.close();
}
public static void Demo3 throws IOException {
FileInputStream fis = new FileInputStream("致青春.mp3");
BufferedInputStream bis = new BufferedInputStream(fis); //包装输入流
FileOutputStream fos = new FileOutputStream("copy.mp3");
BufferedOutputStream bos = new BufferedOutputStream(fos); //包装输出流
int b;
while((b = bis.read()) != -1) { //读一次先将缓冲区读满,再一个一个的返给b
bos.write(b); //写一次,是先将缓冲区装满,再一起写出
}
bis.close();
bos.close();
}
}
8、字节流读取中文是有弊端的,有可能会读到半个中文
1,用字符流读
2,ByteArrayOutputStream
字节流只写中文,可以写
但是需要将字符串转换成字节数组写出去
public class Demo6_Chinese {
public static void main(String[] args) throws IOException {
//demo1();
FileOutputStream fos = new FileOutputStream("bbb.txt");
fos.write("还能一起愉快的玩耍吗?".getBytes());
fos.close();
}
private static void demo1() throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream("aaa.txt");
int b;
while((b = fis.read()) != -1) { //读取的是半个中文
System.out.println(b); //打印的是半个中文
}
fis.close();
}
}
9、标准的异常处理代码
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo7_TryFinally {
/**
* @param args
* 标准的异常处理代码
* @throws IOException
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//1.7版本的处理异常
try(
FileInputStream fis = new FileInputStream("aaa.txt");
FileOutputStream fos = new FileOutputStream("bbb.txt");
MyClose mc = new MyClose();
){
int b;
while((b = fis.read()) != -1) {
fos.write(b);
}
}
}
//1.7版本之前的标准处理异常
private static void demo1() throws FileNotFoundException, IOException {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream("aaa.txt");
fos = new FileOutputStream("bbb.txt");
int b;
while((b = fis.read()) != -1) {
fos.write(b);
}
} finally {
try{
if(fis != null)
fis.close();
}finally {
if(fos != null)
fos.close();
}
}
}
}
class MyClose implements AutoCloseable {
@Override
public void close() {
System.out.println("我关了");
}
}