第十四章异常和第十五章 File- IO 流

第十四章异常

概念

​ 异常也就是非正常情况,比如使用空的引用、数组下标越界、内存溢出错误等,这些都是意外的情况,背离我们程序本身的意图。

Java提供了异常对象描述这类异常情况。

Java提供了异常机制来进行处理,通过异常机制来处理程序运行期间出现的错误。通过异常机制,可以更好地提升程序的健壮性。

可以将异常通俗的理解为“陷阱”,程序运行出现异常,就是掉到陷阱了。

注意:

Java异常是描述在一块代码中发生的异常情况(也就是错误)的对象。

异常处理基本流程

第一种情况:

try{

}

catch(){

}

大部分设计良好的catch子句,应当能够分辨出异常情况,然后继续执行,就好像错误根本没有发生一样。

异常处理过程:

(1)当执行过程中遇到异常时,系统会抛出异常(对象)

(2)catch()块捕获异常并处理。

(3)没有被捕获的异常最终都将由默认处理程序进行处理。默认处理程序会显示一个描述异常的字符串,输出异常发生点的跟踪栈,并终止程序。

提示:

  • l 由try保护的语句必须使用花括号括起来(即,它们必须位于一个块中)。不能为单条语句使用try。catch块也不能省略花括号。
  • l try块中发生异常之后直接进入catch块,执行完catch块后也不会再返回到try块。因此,try块中发生异常之后的语句都不会再执行。

第二种情况:多条catch子句

try{

}

catch(){

}

catch(){

}

提示:

l try及其catch语句构成了一个单元。catch子句的作用域被限制在由之前try语句指定的那些语句。

l 执行了一条catch语句之后,会忽略其他catch语句,并继续执行try/catch块后面的代码。

l 当使用多条catch语句时,要重点记住异常子类必需位于它的所有超类之前。

第三种情况:finally

try(){

}

/*可以有多个catch块*/

finally{

}

提示:

  • l 不管是否有异常抛出,都会执行finally块。
  • l 最多只能有一个finally块。
  • l 对于关闭文件句柄、以及释放资源,finally子句都是很有用的。

第四种情况:

try(){

 

}

catch(){

}

catch(){

}finally{

}

提示:

每个try语句至少需要有一个catch子句或一个finally子句。

嵌套的try语句

一条try语句可以位于另外一条try语句中。

如果内层的try语句没有为特定的异常提供catch处理程序,执行流程就会跳出该try语句,检查外层try语句的catch处理程序,查看异常是否匹配。这个过程会一直继续下去,直到找到了一条匹配的catch语句,或直到检查完所有的try语句。如果没有找到匹配的catch语句,则Java运行时系统会处理该异常。

提示:

当涉及方法调用时,可以能会出现不那么明显的try语句嵌套。

异常类型

异常继承体系

Error一般指与JVM相关的错误,如系统崩溃、虚拟机错误、动态链接失败等。

Exception有一个重要子类RuntimeException。所有RuntimeException类及其子类的实例被称为运行时(Runtime)异常。对于您编写的程序而言,这种类型的异常是自动定义的,包括除零和无效数组索引这类情况。

运行时异常之外,称为非运行时异常/编译异常。

Throwable重写了(由Object定义的)toString()方法,从而可以返回一个包含异常描述的字符串。可以使用println()语句显示这个描述。

异常分类

Java的异常分为两大类:checked异常和unchecked异常。

  • l unchecked异常(非检查异常),也称运行时异常(RuntimeException),比如常见的NullPointerException、IndexOutOfBoundsException。对于运行时异常,java编译器不要求必须进行异常捕获处理或者抛出声明,由程序员自行决定。运行异常
  • l checked异常(检查异常),也称非运行时异常(运行时异常以外的异常就是非运行时异常)。Java认为Checked异常都是可以被处理(修复)的异常,所以Java程序必须显式处理Checked异常,否则无法通过编译。编译异常
  • 含义:checked异常是指程序员比较进行检查,必须进行处理。
  • 对于Checked异常的处理方式有如下两种:
  • l 当前方法明确知道如何处理该异常,则应该使用try…catch块来捕获该异常,然后在对应的块中修复该异常。
  • l 当前方法不知道如何处理这种异常,则应该在定义该方法时声明抛出该异常。

常用异常

unchecked异常 运行时异常

要求:看到异常类名,要知道表示哪种错误,知道属于哪类异常

java.lang包中定义的unchecked异常

异 常含 义
ArithmeticException算术错误,例如除零
ArrayIndexOutOfBoundsException数组索引越界
ArrayStoreException使用不兼容的类型为数组元素赋值
ClassCastException无效的转换
EnumConstantNotPresentException试图使用未定义的枚举值
IllegalArgumentException使用非法实参调用方法
IllegalMonitorStateException非法的监视操作,例如等待未锁定的线程
IllegalStateException环境或应用程序处于不正确的状态
IllegalThreadStateException请求的操作与当前线程状态不兼容
IndexOutOfBoundsException某些类型的索引越界
NegativeArraySizeException使用负数长度创建数组
NullPointerException非法使用空引用
NumberFromatException字符串到数字格式的无效转换
SecurityException试图违反安全性
StringIndexOutOfBounds试图在字符串边界之外进行索引
TypeNotPresentExcepton未找到类型
UnsupportedOpetationException遇到一个不支持的操作

常用的checked异常 编译

IOExeption //输入、输出异常

FileNotFoundException //文件不存在异常

SQLException //SQL异常

java.lang包中定义的Checked异常(了解)

异 常含 义
ClassNotFoundException未找到类
CloneNotSupportedException试图复制没有实现Cloneable接口的对象
IllegalAccessException对类的访问被拒绝
InstantiationException试图为抽象类或接口创建对象
InterruptedException一个线程被另一个线程中断
NoSuchFieldException请求的字段不存在
NoSuchMethodException请求的方法不存在
ReflectiveOperationException与反射相关的异常的子类(该异常是由JDK 7新增的)

throw

也可以使用throw语句显式地抛出一个异常。

在throw语句之后的执行流会立即停止,所有后续语句都不会执行。然后检查最近的try块,查看是否存在和异常类型相匹配的catch语句。

throws

如果方法可能引发一个Checked异常,则必须在方法声明中提供throws子句列出了方法可能抛出的异常类型,从而方法的调用者能够保卫它们自己以防备该异常。

throw和throws区别:

l throw抛异常对象,应用在代码块内

l throws声明可能抛出的异常类型,在方法定义后面。

l 如果方法内使用throw抛出Checked异常对象,又没有进行try catch处理,则该方法定义同时需要使用throws指明抛出异常类型

异常的传播

public class TestException {

static boolean a() throws Exception {

   b();

}

static boolean b() throws Exception {

   c();

}

static boolean c() throws Exception {

try{int i = 5/0;}catch(Exception e){throw e;}return false;}

  public static void main(String [] args){try{a();}catch(Exception e){System.out.println(e.getMessage());}

}

}

自定义异常

自己写类继承自Exception或RuntimeException

自定义异常必须先throw自定义异常的对象,然后才能捕获catch(自定义异常对象)。

Exception定义了四个构造函数。其中的两个支持链式异常,链式异常将在下一节描述。另外两个如下所示:

Exception( )

Exception(String msg)

第十五章 File- IO 流

文件操作 - File

1.1 File 类的概述

File 类用于表示文件和目录路径名的抽象表示。通过 File 类,Java程序可以对文件和目录进行操作,例如创建、删除、重命名和检查文件属性等。

1.2 File 类的常用构造方法

  • File(String pathname): 根据给定的路径名字符串创建一个新的 File 实例。
  • File(String parent, String child): 根据父路径名字符串和子路径名字符串创建一个新的 File 实例。
  • File(File parent, String child): 根据父抽象路径名和子路径名字符串创建一个新的 File 实例。

1.3 File 类的常用方法

创建文件和目录
  • boolean createNewFile(): 创建一个新的空文件,如果文件已存在则返回 false
  • boolean mkdir(): 创建一个目录,如果目录已存在则返回 false
  • boolean mkdirs(): 创建包括必要但不存在的父目录在内的所有目录。
删除文件和目录
  • boolean delete(): 删除文件或目录,如果删除成功则返回 true
查询文件和目录属性
  • boolean exists(): 检查文件或目录是否存在。
  • boolean isFile(): 检查是否是一个文件。
  • boolean isDirectory(): 检查是否是一个目录。
  • String getName(): 获取文件或目录的名称。
  • String getAbsolutePath(): 获取文件或目录的绝对路径。
获取目录内容
  • String[] list(): 返回一个包含目录中所有文件和目录名的字符串数组。
  • File[] listFiles(): 返回一个包含目录中所有文件和目录的 File 对象数组。

1.4 File 类的案例

import java.io.File;
import java.io.IOException;

public class FileExample {
    public static void main(String[] args) {
        File file = new File("example.txt");
        
        // 创建文件
        try {
            if (file.createNewFile()) {
                System.out.println("File created: " + file.getName());
            } else {
                System.out.println("File already exists.");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        // 创建目录
        File directory = new File("exampleDir");
        if (directory.mkdir()) {
            System.out.println("Directory created: " + directory.getName());
        } else {
            System.out.println("Directory already exists.");
        }
        
        // 查询文件和目录属性
        if (file.exists()) {
            System.out.println("File exists.");
            System.out.println("File name: " + file.getName());
            System.out.println("Absolute path: " + file.getAbsolutePath());
            System.out.println("Is file: " + file.isFile());
            System.out.println("Is directory: " + file.isDirectory());
        }
        
        // 获取目录内容
        String[] filesList = directory.list();
        if (filesList != null) {
            for (String fileName : filesList) {
                System.out.println("Directory content: " + fileName);
            }
        }
    }
}

I/O 流

2.1 I/O 流的概述

I/O 流用于处理输入和输出操作。Java 提供了多种类来处理字节流和字符流。I/O 流主要分为以下几类:

  • 字节流:用于处理二进制数据

    • 输入流:InputStream
    • 输出流:OutputStream
  • 字符流:用于处理字符数据

    • 输入流:Reader
    • 输出流:Writer

2.2 字节流

字节流用于处理所有类型的I/O,包括二进制文件和文本文件。它以字节(8位)为单位处理数据。

输入字节流 (InputStream)

InputStream 是所有字节输入流的超类,常用子类包括 FileInputStreamByteArrayInputStreamBufferedInputStream

  • int read(): 读取一个字节并返回。如果已到达流的末尾,则返回 -1。
  • int read(byte[] b): 将字节读入数组 b,返回读取的字节数。
  • void close(): 关闭输入流并释放与该流相关的所有资源。
输出字节流 (OutputStream)

OutputStream 是所有字节输出流的超类,常用子类包括 FileOutputStreamByteArrayOutputStreamBufferedOutputStream

  • void write(int b): 写入一个字节。
  • void write(byte[] b): 将字节数组 b 写入输出流。
  • void close(): 关闭输出流并释放与该流相关的所有资源。

2.3 字符流

字符流用于处理字符数据。它以字符(16位)为单位处理数据。

输入字符流 (Reader)

Reader 是所有字符输入流的超类,常用子类包括 FileReaderCharArrayReaderBufferedReader

  • int read(): 读取一个字符并返回。如果已到达流的末尾,则返回 -1。
  • int read(char[] cbuf): 将字符读入数组 cbuf,返回读取的字符数。
  • void close(): 关闭输入流并释放与该流相关的所有资源。
输出字符流 (Writer)

Writer 是所有字符输出流的超类,常用子类包括 FileWriterCharArrayWriterBufferedWriter

  • void write(int c): 写入一个字符。
  • void write(char[] cbuf): 将字符数组 cbuf 写入输出流。
  • void close(): 关闭输出流并释放与该流相关的所有资源。

2.4 缓冲流

缓冲流用于提高I/O操作的性能,通过提供一个缓冲区来减少实际的I/O操作次数。

缓冲输入流 (BufferedInputStreamBufferedReader)
  • BufferedInputStream:用于字节输入流的缓冲。
  • BufferedReader:用于字符输入流的缓冲。
缓冲输出流 (BufferedOutputStreamBufferedWriter)
  • BufferedOutputStream:用于字节输出流的缓冲。
  • BufferedWriter:用于字符输出流的缓冲。

2.5 I/O 流的案例

使用字节流进行文件复制
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class ByteStreamExample {
    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("example.txt");
             FileOutputStream fos = new FileOutputStream("example_copy.txt")) {
            int data;
            while ((data = fis.read()) != -1) {
                fos.write(data);
            }
            System.out.println("File copied successfully using byte streams.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
使用字符流进行文件复制
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CharStreamExample {
    public static void main(String[] args) {
        try (FileReader fr = new FileReader("example.txt");
             FileWriter fw = new FileWriter("example_copy.txt")) {
            int data;
            while ((data = fr.read()) != -1) {
                fw.write(data);
            }
            System.out.println("File copied successfully using character streams.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
使用缓冲流进行文件复制
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class BufferedStreamExample {
    public static void main(String[] args) {
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("example.txt"));
             BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("example_copy.txt"))) {
            int data;
            while ((data = bis.read()) != -1) {
                bos.write(data);
            }
            System.out.println("File copied successfully using buffered streams.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
使用缓冲字符流读取文件内容并输出到控制台
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderExample {
    public static void main(String[] args) {
        try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) {
            String

 line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

结合 File 类和 I/O 流进行文件操作

通过结合 File 类和 I/O 流,可以实现更复杂的文件操作,例如检查文件是否存在,读取文件内容,写入文件内容等。

3.1 读取文件内容并输出到控制台

import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;

public class FileReadExample {
    public static void main(String[] args) {
        File file = new File("example.txt");
        if (file.exists() && file.isFile()) {
            try (BufferedReader br = new BufferedReader(new FileReader(file))) {
                String line;
                while ((line = br.readLine()) != null) {
                    System.out.println(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            System.out.println("File does not exist or is not a file.");
        }
    }
}

3.2 向文件写入内容

import java.io.File;
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.io.IOException;

public class FileWriteExample {
    public static void main(String[] args) {
        File file = new File("example.txt");
        try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
            bw.write("Hello, world!");
            bw.newLine();
            bw.write("This is an example of writing to a file.");
            System.out.println("File written successfully.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.3 文件复制(综合示例)

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class FileCopyExample {
    public static void main(String[] args) {
        File sourceFile = new File("example.txt");
        File destFile = new File("example_copy.txt");
        
        if (!sourceFile.exists() || !sourceFile.isFile()) {
            System.out.println("Source file does not exist or is not a file.");
            return;
        }
        
        try (FileInputStream fis = new FileInputStream(sourceFile);
             FileOutputStream fos = new FileOutputStream(destFile)) {
            byte[] buffer = new byte[1024];
            int length;
            while ((length = fis.read(buffer)) > 0) {
                fos.write(buffer, 0, length);
            }
            System.out.println("File copied successfully.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 37
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值