异常机制Exception
异常
指程序中出现的不期而至的各种情况:文件找不到、网络连接失败、非法参数等。
异常处理
try…catch…
try{
//尝试执行的代码
}catch(Exception e//想要捕获的异常类型){
//出现异常之后的处理代码
//可以有多个catch(){}最大的异常要放在后面
}finally{
//一定会执行的代码,例如关闭资源
//即是try...catch...中有return,finally也会执行
//可以不要finally
}
//特点:处理完异常后,程序继续执行
throws(抛出,调用者处理)
- 调用者处理方案(两种)
- 接着抛出
- 采用try…catch…
- 特点:执行结束后,程序不再继续执行
自定义异常
步骤
- 创建自定义异常类(继承Exception类);
- 在方法中通过throw关键字抛出异常对象;
- 如果在当前抛出异常的方法中处理异常,可以使用try…catch…语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作;
- 在出现异常方法的调用者中捕获并处理异常。
IO流
IO流能干什么
在本地磁盘和网络上操作数据
流:内存与存储设备之间传输数据的通道
IO流分类
- 按数据流向分为
- 输入流
- 输出流
- 按操作方式分
- 字节流:以字节为单位可以读写所有数据
- 字符流:以字符为单位只能读写文本数据
- 按功能分
- 节点流:具有实际传输数据的读写功能
- 过滤流:在字节流的基础之上增强功能
IO流体系
InputStream、OutputStream、Reader、Writer均为抽象类
字节流读写文件
字节流拷贝文件——按单个字节读写
- 创建字节流读文件对象
InputStream is = new FileInputStream("1.jpg");
- 创建字节流写文件对象
OutputStream os = new FileOutputStream("2.jpg");
-
异常处理
-
使用while循环读写数据
int b;
while((b = is.read())!=-1){
os.write(b);
}
- 关闭资源
is.close();
os.close();
字节流拷贝文件——按字节数组读写
- 创建字节流读文件对象
InputStream is = new FileInputStream("1.jpg");
- 创建字节流写文件对象
OutputStream os = new FileOutputStream("2.jpg");
-
异常处理
-
使用字节数组读写数据
byte[] b = new byte[2048];
int len;
while((len = is.read(b))!=-1){
os.write(b,0,len);
}
- 关闭资源
is.close();os.close();
字节缓冲流拷贝文件
- 创建字节缓冲流读文件对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("1.jpg"));//节点流/底层流
- 创建字节流写文件对象
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("2.jpg"));
-
异常处理
-
读写数据
int len;while((len = bis.read())!=-1){//bis本身其实有缓冲区了,也可以自己创建一个缓冲区byte[] buf = new byte[2048]; bos.write(len);//先写入缓冲区 bos.flush();//刷新操作}
- 关闭资源
bis.close();bos.close();//内部会调用flush()方法,所有上面那里可以不用刷新
缓冲流:
- 提高IO效率,减少访问磁盘的次数;
- 数据存储在缓冲区中,flush()是将缓冲区的内容写入文件中,也可以之间close()
实例一:FileInputStream的使用
package com.io.first;import java.io.FileInputStream;/** * FileInputStream的使用 * 文件输入字节流 */public class Demo01 { public static void main(String[] args) throws Exception { //1.创建FileInputStream,并指定文件路径 FileInputStream fis = new FileInputStream("d:\\aaa.txt");//需要异常处理 //2.读取文件read() //2.1单个字节读取// int b;// while ((b=fis.read())!=-1) {// System.out.print((char) b);// }// System.out.println();// System.out.println("执行完毕"); //2.2一次读取多个字节 byte[] buf = new byte[1024]; int len = 0; while ((len = fis.read(buf))!=-1) { //String(byte[] byte,int start,int length)将字节数组转换成字符串的带三个参数的构造函数 System.out.println(new String(buf,0,len)); } System.out.println("执行完毕"); //关闭资源 fis.close(); }}
实例二:FileOutputStream的使用
package com.io.first;import java.io.FileOutputStream;import java.nio.charset.StandardCharsets;public class Demo02 { public static void main(String[] args) throws Exception { //第二个参数可以不用写,表示每次执行都是将上次写入的覆盖掉 //true表示再次执行是继续写入没有覆盖 FileOutputStream fos = new FileOutputStream("d:\\bbb.txt",true); //单字节写入// fos.write(97);// fos.write('b');// fos.write('c');// System.out.println("执行完毕"); //多字节写入 String s = "hello world"; fos.write(s.getBytes(StandardCharsets.UTF_8)); System.out.println("执行完毕"); //关闭资源 fos.close(); }}
实例三:通过字节流拷贝文件
package com.io.first;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;/** * 通过文件字节流拷贝文件 */public class Demo03 { public static void main(String[] args) throws IOException { //创建文件输入字节流对象 FileInputStream fis = new FileInputStream("d:\\h1.jpg"); //创建文件输出字节流对象 FileOutputStream fos = new FileOutputStream("d:\\h2.jpg"); //多字节读入 int len; byte[] buf = new byte[1024]; while ((len = fis.read(buf))!=-1) { fos.write(buf,0,len); } //关闭资源 fis.close(); fos.close(); System.out.println("拷贝完毕"); }}
实例四:BufferedInputStream的使用
package com.io.second;import java.io.BufferedInputStream;import java.io.FileInputStream;import java.io.IOException;/** * BufferedInputStream的使用 */public class Demo1 { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("d:\\aaa.txt"); BufferedInputStream bis = new BufferedInputStream(fis); int data; while ((data = bis.read())!=-1) { System.out.print((char) data); } //关闭资源 bis.close(); }}
实例五:BufferedOutputStream的使用
package com.io.second;import java.io.BufferedOutputStream;import java.io.FileOutputStream;import java.io.IOException;import java.nio.charset.StandardCharsets;/** * BufferedOutputStream的使用 */public class Demo2 { public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream("d:\\ccc.txt"); BufferedOutputStream bos = new BufferedOutputStream(fos); for (int i = 0;i < 3;i++){ bos.write("hello world\r\n".getBytes(StandardCharsets.UTF_8)); bos.flush(); } System.out.println("执行完毕"); bos.close(); }}
实例六:字节缓冲流拷贝文件
package com.io.second;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;/** * 字节缓冲流拷贝文件 */public class Demo3 { public static void main(String[] args) throws Exception { BufferedInputStream bis = new BufferedInputStream (new FileInputStream("d:\\h2.jpg")); BufferedOutputStream bos = new BufferedOutputStream (new FileOutputStream("d:\\h3.jpg")); int len; while ((len = bis.read())!=-1) { bos.write(len); bos.flush(); } //关闭资源 bis.close(); bos.close(); System.out.println("拷贝完成"); }}
字符流读写文件
字符流读数据——按单个字符读取
- 创建字符流读文件对象
Reader reader = new FileReader("a.txt");
-
异常处理
-
使用while循环读数据
int ch;while((ch = reader.read())!=-1){ System.out.println(ch);}
- 关闭资源
reader.close();
字符流读数据——按字符数组读取
- 创建字符流读文件对象
Reader reader = new FileReader("a.txt");
-
异常处理
-
读数据
char[] chs = new char[1024];int len;while((len = reader.read(chs))!=-1){ String s = new String(chs,0,len);//chs表示要操作的数组;0表示起始索引;len表示要操作的字符个数 System.out.println(s);}
- 关闭资源
reader.close();
字符流写数据——按单个字符写入
- 创建字符流写文件对象
Writer writer = new FileWriter("b.txt");
-
异常处理
-
写数据
writer.write('中');//写一个字符
- 关闭资源
writer.close();
字符流写数据——按字符数组写入
- 创建字符流写文件对象
Writer writer = new FileWriter("b.txt");
-
异常处理
-
写数据
char [] chs = {'a','b','c','d'};fw.write(chs);
- 关闭资源
writer.close();
字符流写数据——按字符串写入
- 创建字符流写文件对象
Writer writer = new FileWriter("b.txt");
-
异常处理
-
写数据
String s = "好好学习";fw.write(s);
- 关闭资源
writer.close();
字符流拷贝文件——按单个字符读写
- 创建字符流读文件对象
Reader reader = new FileReader("a.txt");
- 创建字符流写文件对象
Writer writer = new FileWriter("b.txt");
- 拷贝数据
int data = reader.read();writer.write(data);
- 异常处理
- 关闭资源
reader.close();writer.close();
字符流拷贝文件——按字符数组读写
- 创建字符流读文件对象
Reader reader = new FileReader("a.txt");
- 创建字符流写文件对象
Writer writer = new FileWriter("b.txt");
- 拷贝数据
char[] chs = new char[1024];int len = reader.read(chs);writer.write(chs,0,len);
- 异常处理
- 关闭资源
reader.close();writer.close();
字符缓冲流拷贝文件
- 创建字符缓冲流读文件对象
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
- 创建字符缓冲流写文件对象
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
- 拷贝数据
int len;while((len = br.read())!=-1){ bw.write(len);}
- 异常处理
- 关闭资源
br.close();bw.close();
字符缓冲流——一次读写一行(独有用法)
- 创建字符缓冲流读文件对象
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
- 创建字符缓冲流写文件对象
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
- 拷贝数据
String str;while((str = br.readLine())!=null){ bw.write(str); bw.newLine();//根据系统给操作符,写入一个行分隔符(换行符)}
- 异常处理
- 关闭资源
br.close();bw.close();
实例一:字符流读数据——按单个字符读取
package com.io.fourth;import java.io.FileReader;/** * 字符流读数据——按单个字符读取 * FileReader的使用 */public class Demo01 { public static void main(String[] args) throws Exception{ //创建对象 FileReader fr = new FileReader("d:\\aaa.txt"); int data; while ((data = fr.read())!=-1) { System.out.print((char) data); } //关闭资源 fr.close(); }}
实例二:字符流读数据——按字符数组读取
package com.io.fourth;import java.io.FileReader;/** * 字符流读数据——按字符数组读取 * FileReader的使用 */public class Demo02 { public static void main(String[] args) throws Exception{ //创建对象 FileReader fr = new FileReader("d:\\aaa.txt"); char [] chs = new char[1024]; int len = 0; while ((len = fr.read(chs))!=-1) { String s = new String(chs,0,len); System.out.println(s); } //关闭资源 fr.close(); }}
实例三:FileWriter的用法
package com.io.fourth;import java.io.FileWriter;/** * 字符流写数据 * FileWriter的用法 */public class Demo03 { public static void main(String[] args) throws Exception{ FileWriter fw = new FileWriter("d:\\ddd.txt"); //按单个字符写入 for (int i = 0; i < 3; i++) { fw.write('中'); } //按字符数组写入 char [] chs = {'a','b','c','d'}; fw.write(chs); //按字符串写入 String s = "好好学习"; fw.write(s); System.out.println("执行完毕"); //关闭资源 fw.close(); }}
实例四:字符缓冲流拷贝文件
package com.io.fourth;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileReader;import java.io.FileWriter;/** * 字符缓冲流拷贝文件 * 只能拷贝文本文件 * 不能拷贝图片二进制文件(用字节流拷贝) */public class Demo04 { public static void main(String[] args) throws Exception{ //创建字符流读文件对象 BufferedReader br = new BufferedReader (new FileReader("d:\\aaa.txt")); //创建字符流写文件对象 BufferedWriter bw = new BufferedWriter (new FileWriter("d:\\bbb.txt")); //单个字符拷贝 int data; while ((data = br.read())!=-1) { bw.write(data); bw.flush(); } System.out.println("拷贝完成"); //关闭资源 br.close(); bw.close(); }}
实例五:字符缓冲流独有用法——一次读写一行
package com.io.fourth;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileReader;import java.io.FileWriter;/** * 字符缓冲流独有用法——一次读写一行 */public class Demo05 { public static void main(String[] args) throws Exception{ BufferedReader br = new BufferedReader (new FileReader("d:\\ddd.txt")); BufferedWriter bw = new BufferedWriter (new FileWriter("d:\\e.txt")); String s; while ((s = br.readLine())!=null){ bw.write(s); bw.newLine();//写入一个换行符 } System.out.println("拷贝完成"); //关闭资源 br.close(); bw.close(); }}
对象流
ObjectOutputStream/ObjectInputStream
功能
- 增强了缓冲区功能;
- 增强了读写8种基本数据类型和字符串功能;
- 增强了读写对象的功能:
- readObject() 从流中读取一个对象(反序列化)
- writeObject() 向流中写入一个对象(序列化)
使用流传输对象的过程称为序列化、反序列化
注意点
- 对象要实现Serializable接口才能序列化(该接口是标记接口:无方法、无常量);
- 其中的属性也要实现该接口;
- serialVersionUID:序列化版本号ID,保证序列化的类和反序列化的是同一个类;
- 使用transient(瞬间的)修饰属性,该属性不能被序列化;
- 静态属性也不能序列化;
- 序列化多个对象时,可以借助集合实现。
实例一:序列化
//Student类package com.io.third;import java.io.Serializable;public class Student implements Serializable { private String name; private int age; public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; }}
Student类的序列化
package com.io.third;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;/** * 对象的序列化 * ObjectOutputStream的使用 * 对象要实现Serializable接口 */public class Demo01 { public static void main(String[] args) throws IOException { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream("d:\\stu.bin")); Student s = new Student("张三",18); oos.writeObject(s); System.out.println("执行完毕"); oos.close(); }}
实例二:反序列化
package com.io.third;import java.io.FileInputStream;import java.io.IOException;import java.io.ObjectInputStream;/** * 反序列化 * ObjectInputStream的使用 */public class Demo02 { public static void main(String[] args) throws Exception { ObjectInputStream ois = new ObjectInputStream (new FileInputStream("d:\\stu.bin")); Student s =(Student) ois.readObject(); ois.close(); System.out.println("执行完毕"); System.out.println(s.toString()); }}
常见字符编码
- IS0-8859-1
- UTF-8 针对Unicode码表的可变长度字符编码
- GB2312 简体中文
- GBK 简体中文、扩充
- BIG5台湾 繁体中文
当编码方式和解码方式不一致时,会出现乱码
打印流
- 封装了print()/println()方法,支持写入后换行;
- 支持数据原样打印
- 可以用该流将一些数据打印到文件中
实例
package com.io.fourth;import java.io.PrintWriter;/** * 打印流 * PrintWriter的使用 * (1)封装了print() println()方法,支持写入后换行 * (2)支持数据以原样打印 */public class Demo06 { public static void main(String[] args) throws Exception{ PrintWriter pw = new PrintWriter("d:\\a.txt"); pw.println(97); pw.println('c'); pw.println(3.14); pw.println("hello"); System.out.println("执行完毕"); //关闭资源 pw.close(); }}
(桥)转换流
InputStreamReader/OutputStreamWriter
- 可将字节流–>字符流;
- 可设置字符的编码方式
实例
package com.io.fourth;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.nio.charset.StandardCharsets;/** * 转换流,可指定使用的编码 * 可将字节流转换成字符流 * 可设置字符的编码方式 */public class Demo07 { public static void main(String[] args) throws Exception{ //读文件 InputStreamReader isr = new InputStreamReader (new FileInputStream("d:\\ccc.txt"), StandardCharsets.UTF_8); int data; while ((data = isr.read())!=-1) { System.out.print((char) data); } //写文件 OutputStreamWriter osr = new OutputStreamWriter (new FileOutputStream("d:\\c.txt"), "gbk"); for (int i = 0; i < 10; i++) { osr.write("我爱中国\r\n"); } System.out.println("执行完毕"); //关闭资源 isr.close(); osr.close(); }}
File类
代表物理盘符中的一个文件或文件夹
构造方法
- File(String pathname)
- File(String parent,String child)
- File(File parent,String child)
成员方法
- createNewFile() 创建文件,不存在则创建,存在返回false
- mkdir() mkdirs() 创建目录,不存在则创建,存在返回false
- isDirectory() 判断File对象是否是目录(文件夹)
- isFile() 判断File对象是否是文件
- exists() 判断File对象是否存在
- delete() 删除文件或空目录
- getAbsolutePath() 获取绝对路径
- getPath() 获取文件的相对路径
- getName() 获取文件名
- list() 获取指定目录下所有文件(夹)名称数组
- listFiles() 获取指定目录下所有文件(夹)File数组
- length() 获取文件的长度
- renameTo() 修改文件名
File类的使用
package com.io.five;import java.io.File;import java.io.FileFilter;import java.util.Date;/** * File类的使用 * (1)分隔符 * (2)文件操作 * (3)文件夹操作 */public class FileDemo { public static void main(String[] args) throws Exception { getSeparator();//分隔符 fileOperator();//文件操作 dirOperator();//文件夹操作 } //分隔符 public static void getSeparator() { System.out.println("路径分隔符:"+ File.pathSeparator); System.out.println("名称分隔符:"+File.separator); } //文件操作 public static void fileOperator() throws Exception{ //1.创建文件 //先创建File对象 File file = new File("D:\\file.txt"); //创建文件 if (!file.exists()) { boolean newFile = file.createNewFile(); System.out.println("文件创建结果:"+newFile); } //2.删除文件 //2.1直接删除// System.out.println("删除结果"+file.delete()); //2.2通过jvm退出时删除// file.deleteOnExit();// Thread.sleep(5000);//休眠 //3.获取文件信息 System.out.println("获取文件的相对路径:"+file.getAbsolutePath()); System.out.println("获取文件路径:"+file.getPath()); System.out.println("获取文件名称:"+file.getName()); System.out.println("获取文件父目录:"+file.getParent()); System.out.println("获取文件长度:"+file.length()); System.out.println("获取文件创建时间:"+new Date(file.lastModified()).toLocaleString()); //4.判断 System.out.println("是否可写:"+file.canWrite()); System.out.println("是否是文件:"+file.isFile()); System.out.println("是否隐藏:"+file.isHidden()); } //文件夹操作 public static void dirOperator() throws Exception { //1.创建文件夹 File dir = new File("d:\\aaa\\bbb\\ccc");//多级文件夹 if (!dir.exists()) { //dir.mkdir()只能创建单级文件夹 System.out.println("创建结果:"+dir.mkdirs()); } //2.删除文件夹 //2.1直接删除(只能删除最底层的文件夹且为空时才能删除)// System.out.println("删除结果:"+dir.delete()); //2.2通过jvm退出时删除// dir.deleteOnExit();// Thread.sleep(5000); //3.获取文件夹信息 System.out.println("获取文件夹绝对路径:"+dir.getAbsolutePath()); System.out.println("获取文件夹路径:"+dir.getPath()); System.out.println("获取文件夹名称(最里层):"+dir.getName()); System.out.println("获取文件夹父目录:"+dir.getParent()); System.out.println("获取文件夹的创建时间:"+ new Date(dir.lastModified()).toLocaleString()); //4.判断 System.out.println("是否是文件夹:"+dir.isDirectory()); System.out.println("是否被隐藏:"+dir.isHidden()); System.out.println("-----------------------------"); //5.遍历文件夹 File dir1 = new File("C:\\Users\\WIN\\Pictures\\toonme"); String[] files = dir1.list(); for (String file : files) { System.out.println(file); } System.out.println("----------FileFilter接口的使用-------------"); File[] files1 = dir1.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { if (pathname.getName().endsWith(".jpg")) { return true; } return false; } }); for (File file : files1) { System.out.println(file.getName()); } }}
FileFilter接口
-
public interface FileFilter{ boolean accept(File pathname);}
-
当调用File类中的listFiles()方法时,支持传入FileFilter接口实现类,对获取文件进行过滤,只有满足条件的文件才可出现在listFiles()的返回值中
package com.io.five;import java.io.File;/** * 案例:通过递归遍历文件夹、删除文件夹 */public class FileDemo1 { public static void main(String[] args) { listDir(new File("D:\\新建文件夹")); deleteDir(new File("D:\\新建文件夹")); } //案例一:通过递归遍历文件夹 public static void listDir(File dir) { File[] files = dir.listFiles(); System.out.println(dir.getAbsoluteFile()); if (files.length > 0 && files!=null) { for (File file : files) { if (file.isDirectory()) { listDir(file);//递归调用 } else { System.out.println(file.getAbsoluteFile()); } } } } //案例二:通过递归删除文件夹 public static void deleteDir(File dir) { File[] files = dir.listFiles(); if (files!=null && files.length > 0) { for (File file : files) { if (file.isDirectory()) { deleteDir(file); } else { System.out.println(file.getAbsoluteFile()+"的删除结果:"+file.delete()); } } } System.out.println(dir.getAbsoluteFile()+"的删除结果:"+dir.delete()); }}
Properties(属性集合)
- 存储属性名和属性值;
- 属性名和属性值都是字符串类型;
- 没有泛型;
- 和流有关
package com.io.five;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.PrintWriter;import java.util.Map;import java.util.Properties;import java.util.Set;/** * Properties集合的使用 */public class PropertiesDemo { public static void main(String[] args) throws Exception{ //1.创建集合 Properties properties = new Properties(); //2.添加元素 properties.setProperty("username","alice"); properties.setProperty("age","20"); //3.遍历元素 //3.1keySet()方法 System.out.println("-----keySet()方法-----"); for (Object o : properties.keySet()) { System.out.println(o+"="+properties.get(o)); } //3.2entrySet()方法 System.out.println("-----entrySet()方法-----"); for (Map.Entry<Object,Object> entry :properties.entrySet()) { System.out.println(entry.getKey()+"="+entry.getValue()); } //3.3stringPropertyNames()方法 System.out.println("-----stringPropertyNames()方法-----"); for (String s:properties.stringPropertyNames()) { System.out.println(s+"="+properties.getProperty(s)); } //4.和流有关的方法 //4.1 list()方法 PrintWriter pw = new PrintWriter("d:\\print.txt"); properties.list(pw); pw.close(); //4.2 store()方法 保存// FileOutputStream fos = new FileOutputStream("d:\\store.properties");// properties.store(fos,"注释");// fos.close(); //4.3 load()方法 加载 FileInputStream fis = new FileInputStream("d:\\store.properties"); Properties properties1 = new Properties(); properties1.load(fis); System.out.println(properties1); }}