advance阶段
伤情最是晚凉天,憔悴斯人不堪怜。
邀酒摧肠三杯醉,寻香惊梦五更寒。
钗头凤斜卿有泪,荼蘼花了我无缘。
小楼寂寞心宇月,也难如钩也难圆。
啪!今天整理。
异常处理
导致程序的正常流程被中断的事件,叫做异常
文件不存在异常
FileNotFoundException
文件调用的一般流程
File file = new File("C:\\Users\\lhhsd\\Desktop\\基础教学\\text.c");
new FileInputStream(file);
解析异常
ParseException
由于解析函数传入的参数格式不正确
可查异常CheckedException
可查异常为必须处理的异常,比如说想FileNotFoundException,如果不处理,编译器就不会让你通过,也就是说,我必须把可能出现异常的代码段放到try catch中去,或者在方法外面定义上throws函数
运行时异常RuntimeException
也就是说不是必须进行try catch 的异常,即便不进行try catch也不会有编译错误,主要是因为一些异常太过普遍,如果都需要进行捕捉,代码的可读性就会变得很糟糕,常见的异常,比如说想 数组越界,空指针问题
异常处理的方式
- try catch
try{
coding
}catch(exceprion e){
e.printStackTrace();
}
- 多异常处理方法方法
try{
coding
}catch(exception1 e){
coding
}
catch(exception2 e){
coding
}
或者
try {
System.out.println("试图打开 d:/LOL.exe");
new FileInputStream(f);
System.out.println("成功打开");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d = sdf.parse("2016-06-03");
} catch (FileNotFoundException | ParseException e) {
if (e instanceof FileNotFoundException)
System.out.println("d:/LOL.exe不存在");
if (e instanceof ParseException)
System.out.println("日期格式解析错误");
e.printStackTrace();
}
finally模块
无论是否出现异常finally模块里面的内容最终都会执行,如果说finally块中存在return语句的话则会返回finally中的值
throws&&throw
throws表示,本地不处理的异常,我要丢出去位置为方法声明的地方.在方法外面
而throw表示,我如果执行了某一句话,就应该是发生了异常,这个时候我要抛出异常,被外界捕获到,throws只是说明可能会出现异常,而throw表示一定会抛出某个异常对象,在方法内部。
error
值得时系统级别的异常,通常是内存用光了,一般JAVA程序启动的时候,最大可以使用16M的内存,常见的错误时OutMemoryError
不能被捕捉的错误和运行时异常
运行时异常 RuntimeException ,因为这些往往是运行时异常往往是因为人为的代码bug造成的
仅仅靠try-catch是不够的,只能在代码里找出bug修复,不管的话,运行时还是会出错,建议暂停运行程序,修复
面试题常问题:: 运行时异常与非运行时异常的区别:
运行时异常是不可查异常,不需要进行显式的捕捉
非运行时异常是可查异常,必须进行显式的捕捉,或者抛出
错误error时系统级别的异常,无法通过程序代码预先trycatch住
如果出现了RuntimeException异常,那一定是程序的问题。。所以出现这种异常的时候,不应该想着捕获,而是修改你的程序。
Throwable类
Throwable是类,Exception和Error都继承了该类,所以在捕捉的时候也都可以使用Throwable进行捕捉
public class TestException {
public static void main(String[] args) {
File f = new File("d:/LOL.exe");
try {
new FileInputStream(f);
//使用Throwable进行异常捕捉
} catch (Throwable t) {
// TODO Auto-generated catch block
t.printStackTrace();
}
}
}
自定义异常
一般步骤:
继承Exception类,默认提供两个构造方法,有参和无参
class EnemyHeroIsDeadException extends Exception{
public EnemyHeroIsDeadException(){
}
public EnemyHeroIsDeadException(String msg){
super(msg);
}
}
之后可以抛出该异常
I/O文件
I/O文件对象
无论是文件还是文件夹都使用File代表
创建方法
使用绝对路径,或者相对路径进行创建,如果是使用相对路径进行创建更多的是使用
File file = new File("C:\\Users\\lhhsd\\Desktop\\基础教学\\t.c");
System.out.println(file.getAbsoluteFile());
//获取当前文件的绝对路径
File file1 = new File(file,"Lol.exe");
System.out.println(file.getAbsoluteFile());
System.out.println("当前文件是:"+file);//直接输出当前的文件名称
System.out.println(file.exists());//判断当前文件是否存在
System.out.println(file.isDirectory());//判断当前文件是否为目录
System.out.println(file.isFile());//判断当前文件是否为文件
System.out.println(file.length());//判断当前文件的长度
long time = file.lastModified();//判断给当前文件最后一次修改的时间
Date date = new Date(time);
System.out.println(date);
file.setLastModified(0);//设置最后一次修改事件,参数可以为long数字
File file2 =new File("C:\\Users\\lhhsd\\Desktop\\t.c");
file.renameTo(file2);//进行文件的重命名或者位置移动
file.list();//如果当前文件是一个目录,则返回当前目录下的所有的文件
File[]files = file.listFiles();//如果当前文件时一个目录,则返回文件目录下的所有的文件信息,通过文件数组的方式
System.out.println(file.getParent());//以字符串形式返回获取当前文件的上级绝对路径或相对路径
file.getParentFile();//以文件形式返回
file.mkdir();//根据file名称创建文件,父目录必须存在
file.mkdirs();//创建文件夹,如果父文件夹skin不存在,就会创建父文件夹
file.createNewFile();// 创建一个空文件,如果父文件夹skin不存在,就会抛出异常
file.getParentFile().mkdirs(); // 所以创建一个空文件之前,通常都会创建父目录
file.listRoots();// 列出所有的盘符c: d: e: 等等
file.delete();// 刪除文件
file.deleteOnExit();// JVM结束的时候,刪除文件,常用于临时文件的删除
流
当不同的介质之间有数据交互的时候,JAVA就使用流来实现。
数据源可以是文件,还可以是数据库,网络甚至是其他的程序
比如读取文件的数据到程序中,站在程序的角度来看,就叫做输入流
输入流: InputStream
read返回值为-1代表文件结束
输出流:OutputStream
File f = new File("d:/lol.txt");
// 创建基于文件的输入流
FileInputStream fis = new FileInputStream(f);
// 通过这个输入流,就可以把数据从硬盘,读取到Java的虚拟机中来,也就是读取到内存中
所有的数据存放在计算机中都是以数字的形式存放的。 所以字母就需要转换为数字才能够存放。
输入字节流
InputStream是字节输入流,同时也是抽象类,只提供方法声明,不提供方法的具体实现。
FileInputStream 是InputStream子类,以FileInputStream 为例进行文件读取。
FileInputStream的方法 read()
FIle file = new File(url);
FileInputStream f = new FileInputStream(file);
byte[]all = byte [file.length()];
f.read(all);//把f中的数据转换为输入流,传入到byte数组中去
输出字节流
OutputStream是字节输出流,同时也是抽象类,只提供方法声明,不提供方法的具体实现。
FileOutputStream 是OutputStream子类,以FileOutputStream 为例向文件写出数据
FileInputStream的方法 write()
FIle in_file = new File(url);
File out_file = new File(url)
FileInputStream f = new FileInputStream(in_file);
FileOutputStream out = new FileOutputStream (out_file);
byte[]all = byte [file.length()];
f.read(all);//把f中的数据转换为输入流,传入到byte数组中去
out.write(all)//把all数组中的数据转换为输出流,传入到out对应的文件中去
输入字符流
Reader字符输入流
FileReader 是Reader子类,以FileReader 为例进行文件读取
public static void main(String[] args) {
File in_file = new File("d:/text.txt");
File out_file = new File("d:/res.txt");
try(FileReader fileReader = new FileReader(in_file);
FileWriter fileWriter = new FileWriter(out_file)) {
char[]files =new char[(int)in_file.length()];
fileReader.read(files);
fileWriter.write(files);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
输出字符流
Writer字符输出流
关闭流的方法
- 方法一
在try结构体中直接关闭,缺点,触发异常之后直接抛出,不会执行close函数 - 方法二
这是标准的关闭流的方式
- 首先把流的引用声明在try的外面,如果声明在try里面,其作用域无法抵达finally.
- 在finally关闭之前,要先判断该引用是否为空
- 关闭的时候,需要再一次进行try catch处理
finally {
// 在finally 里关闭流
if (null != fis)
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
- 方法三
使用try()方法,jdk开始支持,所有流实现接口叫做AutoCloseable
try(FileInputStream fis = new FileInputStream(f)){
}
在try中定义的方法会自动进行close,并回收相关资源,要求必须在try中进行实例化
编码问题
计算机存放数据只能存放数字,所有的字符都会被转换为不同的数字,常见的编码格式:
ISO支支持英文字符
GBK支持中英文
UNICODE支持万国文
UTF-8瘦身字节码
Java采用的是Unicode。
ANSI 这个不是ASCII的意思,而是采用本地编码的意思。如果你是中文的操作系统,就会使GBK,如果是英文的就会是ISO-8859-1
用FileInputStream 字节流正确读取中文
FileInputStream 处理方法为:
对结果使用 String str = new String(all,“GBK”);
用FileReader 字符流正确读取中文
FileReader得到的是字符,所以一定是已经把字节根据某种编码识别成了字符了。
FileReader是不能手动设置编码方式的,为了使用其他的编码方式,只能使用InputStreamReader来代替,像这样:
new InputStreamReader(new FileInputStream(f),Charset.forName("UTF-8"));
为什么中字前面有一个?
如果是使用记事本另存为UTF-8的格式,那么在第一个字节有一个标示符,叫做BOM用来标志这个文件是用UTF-8来编码的。
缓存流
以介质是硬盘为例,字节流和字符流的弊端:
在每一次读写的时候,都会访问硬盘。 如果读写的频率比较高的时候,其性能表现不佳。
为了解决以上弊端,采用缓存流。
缓存流读入
缓存流在读取的时候,会一次性读较多的数据到缓存中,以后每一次的读取,都是在缓存中访问,直到缓存中的数据读取完毕,再到硬盘中读取。
BufferedReader
缓存字符输入流 BufferedReader 可以一次读取一行数据。
缓存流必须建立在一个存在的流的基础上一般为FileReader
缓存流写入
缓存流在写入数据的时候,会先把数据写入到缓存区,直到缓存区达到一定的量,才把这些数据,一起写入到硬盘中去。按照这种操作模式,就不会像字节流,字符流那样每写一个字节都访问硬盘,从而减少了IO操作。
PrintWriter和BufferWriter的区别
File in_file = new File("d:/text.txt");
File out_file = new File("d:/out.txt");
try( FileReader fileReader = new FileReader(in_file);
FileWriter fileWriter = new FileWriter(out_file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
PrintWriter printWriter = new PrintWriter(fileWriter);
) {
while (true){
String line = bufferedReader.readLine();
if (line==null)break;
System.out.println(line);
printWriter.println(line);
}
flush函数
有时候如果缓存区没有满我们也要直接把内容写入,对PrintWriter对象使用flush方法
数据流
DataInputStream 数据输入流
DataOutputStream 数据输出流
使用数据流的writeUTF()和readUTF() 可以进行数据的格式化顺序读写,通过DataOutputStream 向文件顺序写出 布尔值,整数和字符串。 然后再通过DataInputStream 顺序读入这些数据。
数据输入流和数据输出流都是依赖于其他流的
EOFException
要求DataInputStream 的文件必须由DataOutputStream 写出
File in_file = new File("d:/out.txt");
File out_file = new File("d:/out.txt");
try (
FileInputStream fileInputStream = new FileInputStream(in_file);
FileOutputStream fileOutputStream = new FileOutputStream(out_file);
DataInputStream dataInputStream = new DataInputStream(fileInputStream);
DataOutputStream dataOutputStream = new DataOutputStream(fileOutputStream);
){
dataOutputStream.writeBoolean(true);
dataOutputStream.writeInt(312);
dataOutputStream.writeUTF("hello world");
boolean b = dataInputStream.readBoolean();
int t = dataInputStream.readInt();
String string = dataInputStream.readUTF();
System.out.println(b);
System.out.println(t);
System.out.println(string);
对象流
对象流指的是可以直接把一个对象以流的形式传输给其他的介质,比如硬盘
一个对象以流的形式进行传输,叫做序列化。 该对象所对应的类,必须是实现Serializable接口
即必须有成员变量servialVersional
private static final long servialVersionUID =1L;
public class Hero implements Serializable {
private static final long servialVersionUID =1L;
public String name ;
public float hp;
}
一般使用方法:
Hero hero = new Hero();
hero.name="garen";
hero.hp=812;
File file = new File("d:/garen.lol");
try (
FileOutputStream fileOutputStream = new FileOutputStream(file);
ObjectOutputStream objectOutputStream=new ObjectOutputStream(fileOutputStream);
FileInputStream fileInputStream=new FileInputStream(file);
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
){
objectOutputStream.writeObject(hero);//首先将对象写入对象,之后将再将对象读出
Hero h2= (Hero)objectInputStream.readObject();
System.out.println(h2.name);
System.out.println(h2.hp);
小结
流分为字节流和字符流
字节流又分为数据流对象流
字符流常用的又有缓存流