缓冲字符流:BufferedWriter/PrintWriter和BufferedReader
-
内部也有一个缓冲区,读写文本数据以块读写形式加快效率
-
缓冲字符流有一个特别的功能:可以按行读写文本数据。
-
PrintWriter具有自动行刷新的缓冲字符输出流,实际开发中更常用,它内部总是会自动连接BufferedWriter作为块写加速使用。
package io;
import java.io.*;
import java.nio.charset.StandardCharsets;
/*
缓冲字符流-------最常用的读写字符串的流
是一对高级流,并且是字符流
内部维护一个默认8KB(8192)长度的char数组,还是以块读写形式读写字符以提高读写效率
BuffredWriter和BufferedReader
PrintWriter:按行写入数据
*/
public class PWDemo {
public static void main(String[] args) throws IOException {
//最常用写入字符串方式:
//底层连接了BufferedWriter,连接了OutputStreamWriter,连接了FileOutputStream
PrintWriter pw = new PrintWriter("pw.txt");
pw.println("和我在成都的街头走一走,哦哦哦哦..");
pw.println("直到所有的灯都熄灭了也不停留");
System.out.println("写出完毕");
pw.close();
/*
FileOutputStream fos = new FileOutputStream("pw.txt"); //文件流(低级流)
OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8); //转换流(高级流)
BufferedWriter bw = new BufferedWriter(osw); //缓冲字符流(高级流)
bw.write("和我在成都的街头走一走,哦哦哦哦..");
bw.write("直到所有的灯都熄灭了也不停留");
System.out.println("写出完毕!");
bw.close(); //先调用flush()冲水
*/
}
}
package io;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
/**
*
*/
public class PWDemo2 {
public static void main(String[] args) throws FileNotFoundException {
//文件流(字节流,低级流):将字节写入到文件中
FileOutputStream fos = new FileOutputStream("pw.txt");
//转换流(字符流,高级流):1.负责衔接字符流与字节流 2.将写出的字符转换为字节再写出
OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
//缓冲字符流(字符流,高级流):块文本数据加速(内部缓冲区默认8192个char)
BufferedWriter bw = new BufferedWriter(osw);
//PrintWriter(字符流,高级流): 1.按行写出字符串 2.具有自动行刷新功能
//构造器第1个参数为流,第2个参数可以传入boolean类型的数据来表示是否打开自动刷新功能(flush)
PrintWriter pw = new PrintWriter(bw,true);
Scanner scan = new Scanner(System.in);
System.out.println("请开始输入内容,单独输入exit时退出");
while(true){
String line = scan.nextLine();
if("exit".equals(line)){
break;
}
//当开启自动行刷新后,每当调用println()方法写出一行后都会自动flush()
//注意:print()不会flush的
pw.println(line);
}
pw.close();
}
}
package io;
import java.io.*;
import java.nio.charset.StandardCharsets;
/**
* 缓冲字符输入流读取文本数据
*/
public class BRDemo {
public static void main(String[] args) throws IOException {
//文件流(字节流,低级流)
FileInputStream fis = new FileInputStream("pw.txt");
//转换流(字符流,高级流)
InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8);
//缓冲字符流(字符流,高级流)
BufferedReader br = new BufferedReader(isr);
/*
String readLine():
读取一行字符串,返回的字符串中不包含最后的换行符
如果单独读取到了换行符(一个空行)则返回值为空字符串("")
如果返回值为null,则表示读到了末尾
*/
String line;
while((line=br.readLine())!=null){
System.out.println(line); //换行输出
//System.out.print(line); //没有换行操作
}
br.close();
}
}
IO总结:
-
文件流:低级流/节点流,字节流--------------FileInputStream和FileOutputStream
-
作用:实际连接程序与文件的"管道",读写字节(单字节读写、块读写)
-
-
缓冲字节流:高级流/处理流,字节流--------BufferedInputStream和BufferedOutputStream
-
作用:块读写字节数据加速
-
-
对象流:高级流/处理流,字节流---------------ObjectInputStream和ObjectOutputStream
-
作用:对象序列化和反序列化
-
-
转换流:高级流/处理流,字符流---------------InputStreamReader和OutputStreamWriter
-
作用:衔接字符流与字节流、将字符转换为字节
-
-
缓冲字符流:高级流/处理流,字符流---------BufferedReader和BufferedWriter/PrintWriter
-
作用:块读写文本字符数据加速、按行读写字符串(PrintWriter具有自动行刷新功能)
-
流的选择:读写java对象就用对象流,想读写字符串就是缓冲字符流
异常:
-
java.lang.Throwable是所有异常的顶级超类,它的下面派生了两个子类型:
-
Error:错误,表示系统级别错误,是不可恢复的错误,比如说:虚拟机内存溢出等,Error通过异常处理机制是处理不了的。
-
Exception:异常/意外,表示程序级别的异常,是可以通过异常处理机制恢复的错误,下面有多个派生类表达不同的异常类型
-
异常处理机制解决的问题:
-
正常程序能走完,但因为某些特殊原因(网络问题、突发情况)导致程序无法正常走完,属于意外情况,通过程序逻辑(分支/循环)是无法解决了,这时才需要使用异常处理机制来做个B计划。直白的说:你明知道会发生,但是还没办法通过逻辑来处理的问题,才需要异常处理机制帮助解决。
异常追责过程:
-
当发生错误时,JVM会new一个异常出来,要求代码必须解决。
-
若代码中没有做异常处理,则找到代码所在的方法来处理
-
若代码所在的方法也没有处理,会继续往上追方法,直到追到main方法
-
若main方法也没有处理,则继续找到调用main方法的JVM,最后程序直接终止
-
异常处理机制:
try...catch:若try中代码出现异常,将会被catch捕获,若catch没有捕获住,则程序依然被杀死
package exception;
/**
* java异常处理机制: try...catch
* try{
* 代码片段
* }catch(XXXException e){
* 当try的代码片段出现XXXException时的补救措施
* }
*/
public class TryCatchDemo {
public static void main(String[] args) {
System.out.println("程序开始了...");
try{
/*
try块中某句代码如果出现了异常,那么try块中这句代码以下的代码都不执行了
try语句中如果不出现异常,catch块不执行
*/
String line = null;
System.out.println(line.length());
String line1 = ""; //因为上一句发生了异常,所以try块中此句及以下代码都不会被执行了
System.out.println(line1.charAt(0));
String line2 = "abc";
System.out.println(Integer.parseInt(line2));
}catch(NullPointerException e){ //捕获空指针异常
System.out.println("出现了空指针异常并解决了"); //处理办法
}catch(StringIndexOutOfBoundsException e){ //捕获字符串下标越界异常
System.out.println("出现了字符串下标越界异常并解决了"); //处理办法
//}catch(NullPointerException | StringIndexOutOfBoundsException e){ //若多个异常具有相同处理方式时,可以合并到一个catch中进行处理
// System.out.println("出现空指针或字符串下标越界异常并解决了");
}catch(Exception e){ //可以在最后捕获超类型异常,凡是该异常的子类型都可以被捕获并处理
System.out.println("反正就是出了个错并解决了");
}
System.out.println("程序结束了...");
}
}
finally:是异常处理机制中的最后一块,不能独立存在,它可以跟着try后(try...finally),或最后一个catch后(try...catch...finally)。
注意:
finally可以保证无论try块中是否出现异常,最后finally都必定执行。通常用来做释放资源这类操作。
JDK7之后,java提供了一个新特性:自动关闭特性。旨在IO操作中可以更简洁的使用异常处理机制完成最后的close操作。只有实现了AutoCloseable接口的类才能写在try()中,注意:所有流都实现了AutoCloseable接口。
package exception;
/**
* finally块的演示
*/
public class FinallyDemo {
public static void main(String[] args) {
System.out.println("程序开始了...");
try{
//String line = null;
String line = "";
System.out.println(line.length());
return; //在return之前,会先finally再return
}catch(Exception e){
System.out.println("出错并解决了");
}finally {
System.out.println("finally中的代码执行了");
}
System.out.println("程序结束了...");
}
}
package exception;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 异常处理机制在IO操作中的运用
*/
public class FinallyDemo2 {
public static void main(String[] args) {
System.out.println("程序开始了");
FileOutputStream fos = null;
try{
fos = new FileOutputStream("./a/b/fos.dat");
fos.write(1);
}catch (IOException e){
System.out.println("出现IO异常并解决了");
}finally {
try {
if(fos!=null){
fos.close();
}
}catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("程序结束了");
}
}
package exception;
import java.io.FileOutputStream;
import java.io.IOException;
public class AutoCloseableDemo {
public static void main(String[] args) {
System.out.println("程序开始了");
try(
//自动关闭特性是编译器认可的,代码编译后会变为FinallyDemo2的样子
//在try()中定义的内容最终会被编译器修改为finally中调用close()关闭操作
FileOutputStream fos = new FileOutputStream("fos.dat");
//只有实现了AutoCloseable接口的类才能在此处定义
//String str = "abc"; //编译错误
){
fos.write(1);
}catch(IOException e){
e.printStackTrace();
}
System.out.println("程序结束了");
}
}
throw:用于对外主动抛出一个异常,通常下面两种情况我们主动对外抛出异常:
当程序遇到一个满足语法,但是不满足业务要求时,可以抛出一个异常告知调用者。
package exception;
/**
* 测试异常的抛出
*/
public class Student {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
if(age<0 || age>100){
throw new RuntimeException(); //抛出了一个异常
}
this.age = age;
}
}
package exception;
/**
* 异常的抛出
*/
public class ThrowDemo {
public static void main(String[] args) {
/*
Student zs = new Student();
zs.setAge(1000);
System.out.println("此人的年龄为:"+zs.getAge()+"岁");
*/
Student zs = new Student();
try{
zs.setAge(1000);
System.out.println("此人的年龄为:"+zs.getAge()+"岁");
}catch(RuntimeException e){
System.out.println("年龄不合法");
}
}
}
-
程序执行遇到一个异常,但是该异常不应当在当前代码片段中被解决时可以抛出给调用者。
-
throws:下篇见