java.IO将流按照读写数据的单位划分为字节与字符流
java.io.InputStream和OutputStream是所有字节流的超类,是抽象类
java.io.Reader和Writer则是所有字符流的超类
字节流与字符流的超类互相不存在继承关系,是平级的。
Reader中定义了几个read方法,规定所有字符流都必须具备的读取字符的方法
Writer中定义了几个write方法,规定了所有字符流都必须具备的写出字符的方法
转换流
java.InputStreamReader和OutputStreamWriter
实际开发中当我们进行流连接对文本数据读写时,这几乎是一套必不可少的高级流。但是在流连接中我们不会直接操作这两个流。
转换流意义:
转换流的本质上是一对儿字符流,但是他们是唯一连接在字节流上的字符流,在流连接中起到“转换器”的作用,负责衔接字符与字节流
而字符流由于读写都是字符,字节流读写都是字节,因此转换流在字符与字节中间负责转换。
向文件osw.txt中写入文本数据
FileOutputStream fos = new FileOutputStream("osw.txt");
字符流都是高级流
转换流的其中一个作用就是将写出的字符转换为字节,然后再交给下面链接的字节流将数据写出
OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
字符输出流java.io.Writer中提供了直接写出字符串的方法:
void write(String str)
String line ="总该有点什么内容吧";
osw.write(line);
osw.write("这是补充的");
System.out.println("写出完毕");
使用转换流读取文本数据
将当前源代码读取出来并输出到控制台上
FileInputStream fis = new FileInputStream("./src/io/IsrDemo.java");
InputStreamReader isr = new InputStreamReader(fis);
java.io.Reader中提供了读取字符的方法:
int read()
定义和字节流InputStream上读取一个字节的格式是一样的,但是功能不同
该方法是读取一个字符,因此返回的int值本质上是一个char,因为一个char实际只占用2个字节,因此返回的int值应当只有低16位有数据,高16位补0
因此该方法仍然使用int型-1来表达流读取到末尾了
int d;
while ((d=isr.read())!=-1){
char c = (char) d;
System.out.println(c);
}
缓冲字符流
java.io.BufferedWriter和BufferedReader
缓冲字符流是一对高级流,内部默认维护一个8k(8000)长度的char数组,读写一定是转换为块读写来保证读写效率
java.io.PrintWriter是具有自动行刷新的缓冲字符输出流(内部总是连接着BufferedWrite作为缓冲加速部分),而PW自身的特点是可以按行写出字符串且具有自动行刷新功能
向文件pw.txt中写入文本数据
PrintWriter提供了直接对文件做写操作的构造器
PrintWriter(File file)
PrintWriter(String path)
PrintWriter pw =new PrintWriter("pw.txt");
pw.println("不知道该写什么了,反正这是第一行");
pw.println("这个应该是第二行");
System.out.println("反正写完了");
自行完成流连接的创建
向文件中按行写入文本数据
1创建文件流(低级流,字节流):向字节中写入文本数据,如果希望对文件进行追加,应该在FileOutputStream中打开追加
FileOutputStream fos = new FileOutputStream("pw2.txt");
2创建转换流(高级流,字符流):衔接字节与字符流,负责将写出的字符转换为字节,若需要明确字符集,则应当在转换流OutputStreamWriter上指定
OutputStreamWriter osw = new OutputStreamWriter(fos);
3创建缓冲字符流(高级流,字符流)块写文本数据加速
BufferedWriter bw = new BufferedWriter(osw);
4.创建PrintWriter(高级流,字符流):按行写出字符串,自动行刷新,true:自动flush
PrintWriter pw =new PrintWriter(bw,true);
当我们主动将PrintWriter连接在一个流上时(构造方法第一个参数为连接在哪个流上),那么PrintWriter的构造器就支持再传入一个boolean型参数的重载,如果这个值为, true时,则打开了自动行刷新功能。
所谓自动行刷新:
当我们使用println方法写出一行字符串时,会自动进行一次flush动作。
注意:调用write,print方法是不会自动flush的。
pw.println("第一行");
pw.println("第2行");
开发中如果出现字符串变量与字面量(直接量)进行equals比较时,要使用字面量.equals(变量)的形式。因为字面量一定非空,可以避免空指针的产生
实现简易记事本功能。
将控制台上输入的每一行字符串都按行写入到文件里,如果在控制台上单独输入exit,则程序退出。
Scanner scanner = new Scanner(System.in);
while (true){
String line =scanner.nextLine();
if ("exit".equals(line)){
break;
}
pw.println(line);
java中所有的输出流(无论是字符还是字节流)都支持flush方法。
不过只有缓冲流的flush是真实将自身缓冲区中缓存的数据做强制写出的。而其他的高级流中flush方法的实现仅仅是调用了其连接的流的flush,将该动作传递下去。
将当前源程序输出到控制台上
FileInputStream fis = new FileInputStream("./src/io/BrDemo.java");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
BufferedReader提供了一个方法:
String readLine()
该方法可以读取一行字符串,并将这行内容返回(返回的内容最后不含有换行符),如果该行为空行(只有换行符),那么方法会返回一个空字符串
如果流读取到了末尾,则返回值为null
String line ;
while ((line =br.readLine())!=null){
System.out.println(line);
}
JAVA中所有的异常的顶级超类为:Throwable
而Throwable下面定义了两个子类型:Error和ExceptionError:表示错误,不可挽回的。通常描述的都是系统错误Exception:表示异常,可在程序运行过程中被处理掉的。我们通常仅在异常处理机制中处理Exception
异常处理机制中的:try-catch
语法:
try{
可能出现异常的代码片段
}catch(XXXException e){
处理try中出现XXXException中的代码
}
System.out.println("程序开始了");
try语句块不能单独写,后面必须跟上catch或finally块
try{
String str =null;
System.out.println(str.length());
/*
JVM会实例化对应异常抛出
try语句块中如果某句代码出现了异常,那么其后的所有代码均不执行
*/
System.out.println("!!!!!!!!!!!!!!!!!!");
}catch (NullPointerException e){
/*
e就接收到了System.out.println(str.length());出现的空指针异常
针对该异常的解决方法(B计划),实际要结合业务需求去处理
*/
System.out.println("出现了空指针,但是解决了");
}
/*
catch语句块可以定义多个,针对不同的异常有不同的处理方式时我们可以分开捕获
*/
catch (StringIndexOutOfBoundsException e){
System.out.println("出现了字符串下标越界,并解决了");
}
/**
当try中不同异常具有相同处理方式,可以放在一个catch中
catch (StringIndexOutOfBoundsException|NullPointerException e){
System.out.println("出现了字符串下标越界或者空指针,并解决了");
}
*/
catch (Exception e){
System.out.println("通用解决方法");
}