异常,字节字符流
异常的概念:
指的是程序在运行过程中出现的非正常情况,最终会导致Jvm会产生非正常的停止。
在java等面向过程的编程中,异常本身就是一个类,产生异常就是创建对象并抛出一个异常对象。
java处理异常的方式是中断处理。
异常的根类:
Throwable是所有异常的根类,其下面分为exception和error两个子类。
error:只能通过避免,好比绝症。
Exception:表示异常,可以通过代码的方式进行纠正。
Throwable中常用的方法:
printStackTrace:打印异常信息
getMassage():获取发生异常的原因。
toString():获取异常类型和异常的常用信息,一般不用。
异常的分类:
编译时期异常:
在编译时期,如果没有处理异常,就会编译失败。
运行时期异常:
在运行时期,检查异常,在编译时期,运行异常的编译不会出错。
处理异常的关键字:
try catch finally throw throws
抛出异常throw:
创建一个异常对象。封装一些提示信息。
通过关键字throw就可以完成,异常对象的抛出。
他用在方法内部,用来抛出一个异常对象,将这个对象传递给调用者,并结束方法的执行。
使用格式:
throw new 异常类名;
对于方法的调用者,一种是捕获处理,另一种就是使用throws进行声明处理。
Objects费控判断:
查看源码发现:
/**
* Checks that the specified object reference is not {@code null}. This
* method is designed primarily for doing parameter validation in methods
* and constructors, as demonstrated below:
* <blockquote><pre>
* public Foo(Bar bar) {
* this.bar = Objects.requireNonNull(bar);
* }
* </pre></blockquote>
*
* @param obj the object reference to check for nullity
* @param <T> the type of the reference
* @return {@code obj} if not {@code null}
* @throws NullPointerException if {@code obj} is {@code null}
*/
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
声明异常throws:
throws可以声明多个异常类,用逗号隔开。
捕获异常,try- catch:
try 用来捕获可以出现异常的代码块;
catch 用来处理异常信息。
他们俩必须进行连用。
finally代码块:
有一些代码块,无论异常是否发生,都需要进行执行,异常也有可能导致程序发生跳转,导致有些代码程序执行不到,所有就有了finally代码块,这个里面的代码块是一定能够被执行的。
异常的注意事项:
多个异常分别处理
多个异常一次捕获,多次处理
多个异常一次捕获,一次处理
多个处理时,子类异常需要在父类异常的上面进行处理。
注意:
运行时的异常被抛出可以不进行处理。不捕获,也不抛出。
finally内不能有return语句
父类抛出多个异常,子类重写父类方法时,可以抛出相同或者父类异常的子类或者不抛出异常。
父类没有抛出异常,子类重写父类的该方法也不能抛出异常,只能进行捕获处理,不能抛出。
自定义异常:
什么是异常类:
RegisterException,是一个注册异常类。
异常类如何定义:
自定义编译异常,自定义类但是要继承Exception。
自定义一个运行时期的异常类,继承RuntimeException
练习:
package com.rongyu.day12;
/**
* 测试异常类
*/
public class Dome01 extends Exception {
public Dome01() {
}
public Dome01(String message) {
super(message);
}
}
package com.rongyu.day12;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
/**
* 模拟登录
*/
public class Dome02 {
private static final Map<String,String> user;
static {
user = new HashMap<>();
user.put("zhangsan","111");
user.put("lisi","222");
user.put("wangwu","333");
user.put("zhaoliu","444");
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入用户名:");
String username = scanner.next();
System.out.print("请输入密码:");
String password = scanner.next();
try {
if (register(username,password)){
System.out.println("恭喜"+username+"成功登录!");
}else {
System.out.println("用户"+username+"登陆失败!");
}
} catch (Dome01 dome01) {
dome01.printStackTrace();
}
}
//判断是否存在
public static boolean register(String username,String password) throws Dome01 {
if (username.equals("111")){
throw new Dome01(username+"不能使用该用户名!");
}
Set<String> userna = user.keySet();
for (String s : userna) {
if (!s.equals(username)){
return false;
}
if (!user.get(s).equals(password)){
return false;
}
}
return true;
}
}
什么事IO:
我们把数据的传输可以看做是数据的一种流动,以内存为基准,分为输入input 和 output,流向内存是输入流,流出内存是输出流。
java.io里面的操作,分为输入,输出,输入也叫作读取数据,输出也叫错写出数据。
IO的分类:
输入流:
把数据从其他设备上读取到内存中的流。
输出流:
从内存中把数据写入到其他设备的流。
根据数据类型分类:
字节流:
以字节为单位,读写数据的流。
字符流:
以字符为单位,读写数据的流。
字节流:
计算机是以二进制的方式进行数据存储的,所以什么东西都是字节。
字节输出流:
close()
flush()刷新此输出流并且强制任何缓冲字节被写入
write() 写入
FileOutPutStream:
他是一个文件输出流,用于写入指定的文件。
FileOutPutStream(“文件名”):
如果有这个文件,会清空这个文件里面的数据进行写入,如果没有文件,那么就会创建一个文件。
FileOutPutStream(“文件”):
写入指定的文件。
写出字节流:
writer(int b)
注意:
int型虽然有四个字节,但是只会写出一个字节。
每次操作完成后都要进行close方法。
写出字节数组:
package com.rongyu.day12;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
/**
* 测试 IO 流
*/
public class Dome03 {
public static void main(String[] args) throws Exception {
File file = new File("a.txt");
//true 表示追加数据 false 表示清空数据
FileOutputStream fos = new FileOutputStream(file,false);
byte[] bytes = "荣宇".getBytes();
byte[] bytes1 = "abcdef".getBytes();
fos.write(bytes);
fos.write(bytes1,2,3);
for (int i = 0; i < bytes1.length; i++) {
fos.write("\r\n".getBytes());
fos.write(bytes1[i]);
}
fos.flush();
fos.close();
}
}
字节输入流:
close();
read();
FileInPutStream:
输入流,从文件中读取数据。
他的构造方法与输出流的方法一样。
读取字节数据:
read每次可以读取一个字节的数据,提升为int类型,读取到文件末尾的时候,返回-1。
package com.rongyu.day12;
import java.io.FileInputStream;
/**
* 字节输入流
*/
public class Dome04 {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("a.txt");
int b;
while ((b = fis.read())!=-1){
System.out.println((char)b);
}
fis.close();
}
}
package com.rongyu.day12;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/**
* 使用字节数组测试
*/
public class Dome05 {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("a.txt");
int len;
byte[] b = new byte[5];
while ((len = fis.read(b))!=-1){
System.out.println(new String(b));
}
fis.close();
}
}
案例:
package com.rongyu.day12;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
/**
* 复制文件
*/
public class Dome06 {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("a.txt");
int len;
byte[] b = new byte[6];
FileOutputStream fos = new FileOutputStream("b.txt");
while ((len = fis.read(b))!=-1){
fos.write(b);
}
fos.flush();
fis.close();
fos.close();
}
}
字符流:
它是一种以字符为单位进行读写数据的方式,用来处理文本。
FileReader:
字符编码:
字节与字符对应的规则,Windows系统的中文编码默认是GBK编码。
字符缓冲区:
一个字节数组,用来临时存储字节数组。
Reader:
package com.rongyu.day12;
import java.io.FileNotFoundException;
import java.io.FileReader;
/**
* 读取字符数据
*/
public class Dome07 {
public static void main(String[] args) throws Exception {
FileReader reader = new FileReader("a.txt");
int b;
while ((b = reader.read())!=-1){
System.out.print((char)b);
}
reader.close();
}
}
package com.rongyu.day12;
import java.io.FileReader;
/**
* 测试字符数组
*/
public class Dome08 {
public static void main(String[] args) throws Exception {
FileReader reader = new FileReader("a.txt");
int len;
char[] c = new char[5];
while ((len = reader.read(c))!=-1){
System.out.print(new String(c));
}
reader.close();
}
}
Writer:
package com.rongyu.day12;
import java.io.FileWriter;
import java.io.IOException;
/**
* 测试写出流
*/
public class Dome09 {
public static void main(String[] args) throws IOException {
FileWriter writer = new FileWriter("c.txt",false);
String str = "荣宇";
writer.write(str,0,2);
writer.flush();
writer.close();
}
}
IO的异常处理:
package com.rongyu.day12;
import java.io.FileReader;
import java.io.FileWriter;
/**
* 测试IO的异常处理
*/
public class Dome10 {
public static void main(String[] args) throws Exception {
FileReader reader = new FileReader("a.txt");
FileWriter writer = new FileWriter("d.txt");
try(reader;writer){
int len;
char[] c = new char[5];
while ((len = reader.read(c))!=-1){
writer.write(c,0,len);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
属性集:
util.properties 继承于 HashTable ,表示一个持久的属性集,它使用键值来结构存储数据。
基本存储方法:
setProperty(String key, String value):保存一对属性
getProPerty(String key)
StringPropertyNames():所有键的名称集合
与流相关的方法:
load(InPutStream in):从输入流中读取键值对。
package com.rongyu.day12;
import java.io.FileInputStream;
import java.util.Properties;
import java.util.Set;
/**
* 测试属性集
*/
public class Dome11 {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.load(new FileInputStream("a.txt"));
Set<String> strings = properties.stringPropertyNames();
for (String string : strings) {
System.out.println(string+properties.getProperty(string));
}
}
}
注意:
必须是以键值对的方式,可以使用空格,等号,冒号等符号分隔。
缓冲流:
他也叫高效流,是对4个基本的流的增强。
字节缓冲流:
BufferedInputStream,BufferedOutputStream
字符缓冲流:
BufferReader,BufferedWriter
缓冲流的基本原理,是在创建对象的时候,会创建一个内置的默认的缓冲数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。
package com.rongyu.day12;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* 测试缓冲字节流
*/
public class Dome12 {
public static void main(String[] args) throws Exception {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("e.txt"));
try(bis;bos){
int len;
byte[] b = new byte[5];
while ((len = bis.read(b))!=-1){
bos.write(b,0,len);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
字符缓冲流:
特有方法:
readLine():读一行文字
new Line():写一行分隔符
package com.rongyu.day12;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Map;
/**
* IO流练习之文本排序
*/
public class Dome13 {
public static void main(String[] args) throws Exception {
BufferedReader reader = new BufferedReader(new FileReader("b.txt"));
Map<String,String> map = new HashMap<>();
try(reader){
String b = null;
while ((b = reader.readLine())!=null){
String[] split = b.split("\\.");
map.put(split[0],split[1]);
}
}catch (Exception e){
e.printStackTrace();
}
for (int i = 1; i <= map.size(); i++) {
String s = String.valueOf(i);
System.out.println(s+map.get(s));
}
}
}
转换流:
字符编码:
就是一套自然语言的字符与二进制数之间的对应规则。
编码表:生活中的文字和计算机中对二进制的对应规则。
字符集:
ASCLL字符集:
他的基本的使用7位表示一个字符,共128个字符。ASCLL的扩展字符集使用8位表示一个字符,共256字符。
InputStreamReader:
他是Reader的子类,他会将其解码为字符。就是他可以指定字符编码。
OutputStreamWriter:
Writer的子类,可以从字符流到字节流。
序列化:
一个字节序列表示一个对象,该字节对象表示:对象的数据,对象的类型和对象的存储属性等信息,相当于保存了一个对象的信息。
ObjectOutputStream:
一个对象想要序列化,他需要满足两个条件:
这个类必须实现Serializable解救,他是一个标记接口,不实现这个接口的类不能被序列化或者反序列化。
该类的所有的属性必须是可以被序列化的,如果有一个不可以被序列化,那么必须被transient修饰,表示这个属性是瞬态的。
ObjectInputStream:
反序列化
练习之序列化集合:
package com.rongyu.day12;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
/**
* 序列化集合
*/
public class Dome14 {
public static void main(String[] args) throws Exception {
List<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
// xuliehua(list);
//反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d.txt"));
List<String> o = (List<String>)ois.readObject();
for (String s : o) {
System.out.println(s);
}
}
private static void xuliehua(List<String> list) throws Exception{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("d.txt",false));
oos.writeObject(list);
oos.close();
}
}
打印流:
PrintStream:
使用指定的文件创建一个新的打印流。
改变打印流向:
在这里插入代码片package com.rongyu.day12;
import java.io.PrintStream;
/**
* 测试打印流
*/
public class Dome15 {
public static void main(String[] args) throws Exception {
System.out.println(97);
PrintStream ps = new PrintStream("f.txt");
//设置系统打印流流向
System.setOut(ps);
System.out.println(97);
}
}