java课程笔记

异常

异常就是程序运行时发生的不正常情况,如打开一个不存在的文件,与错误不同(代码错误),异常一般分为两大类:

  • Error:由于java虚拟机的限制而产生的程序错误,一般无法解决。如:JVM系统内部错误、资源耗尽等严重情况。
  • Exception: 其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理
    Error和Exception包含如下:
    ## 异常处理
  • Java采用抓抛模型catch-throw异常处理机制,将异常处理的程序代码集中在一起,与正常的程序代码分开,使得程序简洁,易于维护。
  • 异常对象的生成两种方式

1.由虚拟机自动生成:程序运行过程中,虚拟机检测到程序发生了问题,如果在当前代码中没有找到相应的处理程序,就会在后台自动创建一个对应异常类的实例对象并抛出——自动抛出
2.由开发人员手动创建:创建好的异常对象不抛出对程序没有任何影响,和创建一个普通对象一样

  • 捕获异常
    当一个方法抛出异常时,如果没有实现异常处理,会一直向上寻找异常解决方法,如果一个异常回到main()方法,并且main()也不处理,则程序运行终止。
  • 选择处理异常
    如果这些异常是运行时异常,则方法的调用者有3种选择:
    (1)不理会这些声明,编译可以通过;
    (2)使用try…catch处理异常;
    (3)使用throws继续延迟处理
    如果是非运行时异常,方法调用者有两种选择:
    (1)使用try…catch处理异常;
    (2)使用throws继续延迟处理,让编译先通过。

try——catch捕获异常

  • try-catch语句
    在try语句块中,放置可能出现异常的代码。在catch语句块中是对异常对象进行处理的代码。当try中的保护代码块发生异常时,如果catch块中声明了该异常,异常将会被传递到catch块中。
  • 每个try语句块可以伴随一个或多个catch语句,用于处理可能产生的不同类型的异常对象。
  • 如果明确知道产生的是何种异常,可以用该异常类作为catch的参数;也可以用其父类作为catch的参数,但是参数不能是与已知异常无关的异常类,否则将不会执行
  • try-catch-finally语句
    try-catch-finally语句就是在try-catch语句的基础上,加上finally代码块,finally代码块是无论是否发生异常都会被执行

throw和throws

当程序没有使用try-catch语句捕获异常时,就需要用到throw和throws关键字

  • throws关键字
     throws关键字(必须在定义方法的时候使用),用于声明该方法可能会抛出的异常类型,一般用于不知道该怎么处理异常时,放任其不管,当有异常抛出时会中断该方法,而异常被抛到这个方法的调用者那里。
     使用throws关键字明确指出了该方法可能抛出的异常。throws后面如果声明多个异常类型,之间可用“,”分隔
  • throw关键字
    当创建一个异常对象之后,可以使用throw关键字抛出异常对象。throw必须在方法体中使用。
    手动抛出异常但是有时候有些错误在jvm看来不是错误,所以我们需要自己手动引发异常,这就是throw的作用,例如:
    1
    2
    3
    4
    5
    6
    7
    public void setAge(int age) throws Exception {
    if(age<0){
    Exception e = new ArithmeticException(“年龄不能为负”);
    throw e;
    }
    this.age = age;
    }
  • 注意重写方法不能抛出比被重写方法范围更大的异常类型:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class A {
    public void methodA() throws IOException {
    ……
    } }
    public class B1 extends A {
    public void methodA() throws FileNotFoundException {
    ……
    } }
    public class B2 extends A {
    public void methodA() throws Exception { //报错,抛出的异常类型比父类异常类型大
    ……
    } }

    人工抛出异常

    Java异常类对象除在程序执行过程中出现异常时由系统自动生成并抛出,也可根据需要人工创建并抛出。
  • 人工抛出异常,首先要生成异常类对象,然后通过throw语句实现抛出操作,注意,可抛出的异常必须是Throwable或其子类的实例。
  • 自定义异常类
    自定义异常类是包括人工抛出异常的自定义类:

1.一般地,用户自定义异常类都是RuntimeException的子类。
2.自定义异常类通常需要编写几个重载的构造器。
3.自定义的异常类对象通过throw抛出。
4.自定义异常最重要的是异常类的名字,当异常出现时,可以根据名字判断异常类型。
5.用户自己的异常类必须继承现有的异常类

java文件操作

  • 输入流:即读取源中的数据,输出流:传送数据到目的地
  • 字节输入流:InputStream抽象类的子类创建的流对象
    InputStream类提供的read方法以字节为单位顺序地读取源中的数据,直到源的末尾或输入流被关闭
  • 字节输出流:OutputStream抽象类的子类创建的流对象
    OutputStream的write方法以字节为单位顺序地写文件,直到流被关闭
  • 字符输入流:Reader抽象类的子类创建的流对象
  • 字符输出流:Writer抽象类的子类创建的流对象

File类

File类是对文件和文件夹操作的一个类,它有以下几个功能:

  • 创建文件/文件夹
  • 删除文件/文件夹
  • 查找文件/文件夹(判断是否存在)
  • 获取文件/文件夹
  • 遍历文件夹
  • 获取文件大小
    由于不同操作系统的分隔符可能不同,所以File类有以下成员变量用于表示分隔符:
  • 默认名称分隔符:File.separatorr,即”"
  • 默认路径分隔符:File.pathSeparator,即”;”

File类的创建

File的构造方法有三种:
一个参数:其参数是文件的路径,创建File的对象,其参数表示的文件可以不存在;
两个参数:前者表示父路径,后者表示子路径,组合起来表示文件路径;
两个参数:前者表示父类文件,后者表示子类文件;
当我们直接打印File对象时,将会打印出file的路径,即传递的参数:

1
2
3
4
5
6
7
8
9
File file1 = new File("D:/IDEA/FileMode/1.txt");
System.out.println(file1); //D:\IDEA\FileMode\1.txt

File file2 = new File("D:/IDEA/FileMode/""1.txt");
System.out.println(file2); //D:\IDEA\FileMode\1.txt

File file3 = new File("D:/IDEA/FileMode/");
File file4 = new File(file1,"1.txt");
System.out.println(file4); //D:\IDEA\FileMode\1.txt

File类的方法

1.获取文件路径,名称,大小

  • String getPath(); //获取文件路径
  • String getName(); //获取文件名
  • long length(); //获取文件大小
    1
    2
    3
    4
    5
    6
    File file = new File("D:/IDEA/FileMode/1.txt");
    System.out.println(file.getAbsolutePath()); //D:\IDEA\FileMode\1.txt
    System.out.println(file.getName()); //1.txt
    System.out.println(file.getAbsoluteFile()); //D:\IDEA\FileMode\1.txt
    System.out.println(file.getPath()); //D:\IDEA\FileMode\1.txt
    System.out.println(file.length()); //15

2.判断文件类型及是否存在

  • boolean exists(); //判断文件是否存在
  • boolean isFile(); //判断文件是否位文件
  • boolean isDirectory(); //判断文件是否为文件夹
    1
    2
    3
    4
    File file = new File("D:/IDEA/FileMode/1.txt");
    System.out.println(file.exists()); //true
    System.out.println(file.isFile()); //true
    System.out.println(file.isDirectory()); //false

3.创建,删除文件/文件夹(路径中的后缀无效,默认为名称)

  • boolean createNewFile(); //创建新文件
  • boolean delete(); //删除文件/文件夹
  • boolean mkdir(); //创建单级目录
  • boolean mkdirs(); //创建单级目录或多级目录
    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
    File file1 = new File("D:/javaTestFile/temp1.txt");
    //创建文件
    try{
    if(!file1.exists()) file1.createNewFile();
    }catch (IOException e){
    System.out.println("文件创建失败");
    }

    //创建单级文件夹
    File file2 = new File("D:/javaTestFile/temp2");
    try {
    if(!file2.exists()) file2.mkdirs();
    }catch (NullPointerException e) {
    System.out.println("创建目录失败");
    }

    //创建多级文件夹
    File file3 = new File("D:/javaTestFile/temp3/temp3_1/temp3_2");
    try {
    if(!file3.exists()) file3.mkdirs();
    }catch (NullPointerException e) {
    System.out.println("创建目录失败");
    }

    //删除文件和文件夹
    file1.delete();
    file2.delete();

4.获取文件夹下所有文件及文件夹(路径必须为文件夹路径)

  • String[] list(); //获取文件夹下所有文件和文件夹,返回字符串数组
  • File[] listFiles(); //获取文件夹下所有文件和文件夹,返回文件数组
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    File file = new File("D:/javaTestFile");
    String list[] = file.list();
    for(String s : list){
    System.out.println(s);
    }

    File files[] = file.listFiles();
    for(File f : files){
    System.out.println(f.getName());
    }

遍历多级目录查找目标文件

使用递归遍历目录即可,下面的代码演示了查找javaTestFile目录下的所有txt文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.io.File;

public class FileTest_3 {
public static void main(String[] args) throws NullPointerException{
File file = new File("D:/javaTestFile");
searchFile(file);
}
public static void searchFile(File file){
File lists[] = file.listFiles();
for(File f : lists) {
if (f.isDirectory()) {
searchFile(f);
}
if (f.getName().endsWith("txt")) {
System.out.println(f.getPath());
}
}
}
}

FileFilter——文件过滤器

FileFilter,即文件过滤器,是java库中的一个接口,用于筛选文件,文件过滤器使用原理如下图所示:

使用方法为: - 创建子类实现FileFilter,重写accept方法定义过滤规则,然后将子类对象传递进listFile(FileFilterImpl ff)方法的参数中,示例如下: 1.实现FileFilter,重写accept的规则为查找txt文件
1
2
3
4
5
6
7
8
9
10
11
import java.io.FileFilter;
import java.io.File;

public class FileFilterImpl implements FileFilter {

@Override
public boolean accept(File f) {
return f.isDirectory() || f.getName().endsWith("txt");
}
}

2.创建过滤器过滤文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.io.File;
import java.io.FilenameFilter;

public class FileTest_3 {
public static void main(String[] args) throws NullPointerException{
File file = new File("D:/javaTestFile");
searchFile(file);
}

public static void searchFile(File file){
File lists[] = file.listFiles(new FileFilterImpl());
for(File f : lists) {
if (f.isDirectory()) {
searchFile(f);
}
if (f.getName().endsWith("txt")) {
System.out.println(f.getPath());
}
}
}
}

- 或者使用匿名内部类,下面以FileNameFilter,另一个文件过滤器(效果同FileFilter)示例:
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
import java.io.File;
import java.io.FilenameFilter;

public class FileTest_3 {
public static void main(String[] args) throws NullPointerException{
File file = new File("D:/javaTestFile");
searchFile(file);
}

public static void searchFile(File file){
File lists[] = file.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return new File(dir,name).isDirectory() || name.endsWith("txt");
}
});
for(File f : lists) {
if (f.isDirectory()) {
searchFile(f);
}
if (f.getName().endsWith("txt")) {
System.out.println(f.getPath());
}
}
}
}

RandomAccessFile——随机读写文件

RandomAccessFile即可以读取文件内容,也可以向文件中写入内容,它包含了一个记录指针,用以标记当前读写处的位置,它的每次操作都是在指针所在处,所以它可以直接跳到文件的任意位置来读写数据。

RandomAccessFile的创建

 RandomAccessFile的构造方法有两个参数,第一个是文件,第二个是权限管理:“r” 只读;“rw” 可读可写;“rws” 可读可写,并要求对文件内容或元数据的每个更新都同步写入到底层设备;“rwd” 可读可写,并要求对文件内容每个更新都同步写入到底层设备。

1
2
File file = new File(filePath);
RandomAccessFile raf = new RandomAccessFile(file,"rw"); //可读可写

RandomAccessFile的方法及注意事项

RandomAccessFile常用的方法如下:

  • RandomAccessFile的read()和write()方法,同其他文件操作类
  • long getFilePointer(); //返回文件记录指针的当前位置
  • void seek(long pos); //将文件记录指针定位到pos位置
    注意事项:
  • 在seek方法中指针是从0~n-1的,所以当指针指向length,读取的值是-1
  • 用了RandomAccessFile的read方法后,指针会往后移动一个字符,而readline后会移动到下一行的开头,也就是再read就是下一行的开头第一字符。

RandomAccessFile实现在任意位置写文件和读文件

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
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

public class RamdomAccessFileTest {
public static void main(String[] args) {
//创建readme.txt
File file = new File("D:/javaTestFile/Readme.txt");
try {
if (!file.exists()) {
file.createNewFile();
}
//创建RamdomAccess对象
RandomAccessFile raf = new RandomAccessFile(file, "rw");
//写第一行和第二行
String line1 = "line1";
String line2 = "line2";
raf.write(line1.getBytes());
raf.write("\n".getBytes());
raf.write(line2.getBytes());
//将指针移至第二行开始处
int pos = 0;
while(pos++ < raf.length()){
raf.seek(pos);
if(raf.read() == '\n') break;
pos++;
}
raf.seek(++pos);
//读第二行内容
String l2 = raf.readLine().toString();
System.out.println(l2);
//指针移至文件末尾
String line3 = "line3";
raf.seek(raf.length());
//追加内容写第三行
raf.write("\n".getBytes());
raf.write(line3.getBytes());
raf.close();
}catch (IOException e){
System.out.println("读写异常");
}
}
}

IO流