IO流中的字符输入输出流及try...catch处理流处理中的异常

使用字节流读取中文的问题

import java.io.FileInputStream; import java.io.IOException; /* 使用字节流读取中文文件 1个中文 GBK:占用两个字节 UTF-8:占用3个字节 */ public class Demo01InputStream { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("D:\\environment\\java_project\\javase\\c.txt"); int len = 0; while ((len = fis.read())!=-1){ System.out.println((char)len); //出现错误 } fis.close(); } }

字符输入流读取字符数据
import java.io.FileReader; import java.io.IOException; /* java.io.Reader:字符输入流,是字符输入流的最顶层的父类,定义了一些共性的成员方法,是一个抽象类共性的成员方法: int read() 读取单个字符并返回 int read(char[] cbuf) 一次读取多个字符,将字符读入数组 void close() 关闭该流并释放与之关联的所有资源java.io.FileReader extends InputStreamReader extends Reader FileReader:文件字符输入流 作用:把硬盘文件中的数据以字符的方式读取到内存中构造方法: FileReader(String fileName) FileReader(File file) 参数:读取文件的数据源 String fileName:文件的路径 File file:一个文件 FileReader构造方法的作用: 1.创建一个FileReader对象 2.会把FileReader对象只想要读取的文件 */ public class Demo02Reader { public static void main(String[] args) throws IOException { //1.创建FileReader对象,构造方法中绑定要读取的数据源 FileReader fr = new FileReader("D:\\environment\\java_project\\javase\\c.txt"); //2.使用FileReader对象中的方法read读取文件 //int read() 读取单个字符并返回 /*int len = 0; while ((len = fr.read())!=-1){ System.out.println((char)len); }*///int read(char[] cbuf) 一次读取多个字符,将字符读入数组 char[] cs = new char[1024]; //存储读取到的多个字符 int len = 0; //记录的是每次读取的有效字符个数 while((len = fr.read(cs))!=-1){ /* String类的构造方法 String(char[] value) 把字符数组转换为字符串 String(char[] value, int offset, int count) 把字符数组的一部分转换为字符串 offset数组的开始索引 count转换的个数 */ System.out.println(new String(cs,0,len)); }//3.释放资源 fr.close(); } }

字符输出流FileWriter
import java.io.FileWriter; import java.io.IOException; /* java.io.Writer:字符输出流,是所有字符输出流的最顶层的父类,是一个抽象类共性的成员方法: - void write(int c) 写入单个字符 - void write(char[] cbuf) 写入字符数组 - abstract void write(char[] cbuf, int off, int len) 写入字符数组的某一部分,off数组的开始索引,len写的字符个数 - void write(String str) 写入字符串 - void write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个数 - void flush() 刷新该流的缓冲 - void close() 关闭此流,但要先刷新它java.io.FileWriter extends OutputStreamWriter extends Writer FileWriter:文件字符输出流 作用:把内存中字符数据写入到文件中构造方法: FileWriter(File file) 根据给定的File对象构造一个FileWriter对象 FileWriter(String fileName) 根据给定的文件名构造一个FileWriter对象 参数:写入数据的目的地 String fileName:文件的路径 File file:是一个文件 构造方法的作用: 1.会创建一个FileWriter对象 2.会根据构造方法中传递的文件/文件的路径,创建文件 3.会把FileWriter对象指向创建好的文件字符输出流的使用步骤(重点): 1.创建FileWriter对象,构造方法中绑定要写入数据的目的地 2.使用FileWriter中的方法write,把数据写入到内存缓冲区中(字符转换为字节的过程) 3.使用FileWriter中的方法flush,把内存缓冲区中的数据,刷新到文件中 4.释放资源(会先把内存缓冲区中的数据刷新到文件中) */ public class Demo01Writer { public static void main(String[] args) throws IOException { //1.创建FileWriter对象,构造方法中绑定要写入数据的目的地 FileWriter fw = new FileWriter("D:\\environment\\java_project\\javase\\d.txt"); //2.使用FileWriter中的方法write,把数据写入到内存缓冲区中(字符转换为字节的过程) //void write(int c) 写入单个字符 fw.write(97); //3.使用FileWriter中的方法flush,把内存缓冲区中的数据,刷新到文件中 //fw.flush(); //4.释放资源(会先把内存缓冲区中的数据刷新到文件中) fw.close(); } }

FileWriter中flush方法与close方法的区别
import java.io.FileWriter; import java.io.IOException; /* flush方法和close方法的区别 - flush:刷新缓冲区,流对象可以继续使用 - close:先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了 */ public class Demo02CloseAndFlush { public static void main(String[] args) throws IOException { //1.创建FileWriter对象,构造方法中绑定要写入数据的目的地 FileWriter fw = new FileWriter("D:\\environment\\java_project\\javase\\e.txt"); //2.使用FileWriter中的方法write,把数据写入到内存缓冲区中(字符转换为字节的过程) //void write(int c) 写入单个字符 fw.write(97); //3.使用FileWriter中的方法flush,把内存缓冲区中的数据,刷新到文件中 fw.flush(); //刷新之后流可以继续使用 fw.write(98); //4.释放资源(会先把内存缓冲区中的数据刷新到文件中) fw.close(); //close方法之后流已经关闭了,已经从内存中消失了,流就不能再使用了 fw.write(99); //IOException: Stream closed } }

字符输出流写数据的其他方法
/* 字符输出流写数据的其他方法: - void write(char[] cbuf) 写入字符数组 - abstract void write(char[] cbuf, int off, int len) 写入字符数组的某一部分,off数组的开始索引,len写的字符个数 - void write(String str) 写入字符串 - void write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个数 */ public class Demo03Writer { public static void main(String[] args) throws IOException { FileWriter fw = new FileWriter("D:\\environment\\java_project\\javase\\f.txt"); char[] cs = {'a','b','c','d','e'}; //void write(char[] cbuf)写入字符数组 fw.write(cs); //abcde//void write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个数 fw.write(cs,1,3); //bcd//void write(String str)写入字符串 fw.write("传智播客"); //传智播客//void write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个数 fw.write("天生我材必有用",0,4); //天生我材fw.close(); } }

字符输出流的续写和换行
import java.io.FileWriter; import java.io.IOException; /* 续写和换行 续写,追加写:使用两个参数的构造方法 FileWriter(String fileName, boolean append) FileWriter(File file, boolean append) 参数: String fileName,File file:写入数据的目的地 boolean append:续写开关 true:不会创建新的文件覆盖源文件,可以续写;false:创建新的文件覆盖源文件 换行:换行符号 windows:\r\n linux:/n mac:/r */ public class Demo04Writer { public static void main(String[] args) throws IOException { FileWriter fw = new FileWriter("D:\\environment\\java_project\\javase\\g.txt",true); for (int i = 0; i < 10; i++) { fw.write("HelloWorld"+i+"\r\n"); } fw.close(); } }

使用try...catch处理流中的异常
  • try...catch...finally
import java.io.FileWriter; import java.io.IOException; /* 在jdk1.7之前使用trycatchfinally 处理流中的异常 格式: try{ 可能会产出异常的代码 }catch(异常类变量 变量名){ 异常的处理逻辑 }finally{ 一定会执行的代码 资源释放 } */ public class Demo01TryCatch { public static void main(String[] args) { //提高变量fw的作用域,让finall可以使用 //变量在定义的时候,可以没有值,但是使用的时候必须有值 //fw = new FileWriter("D:\\environment\\java_project\\javase\\g.txt",true); 执行失败,fw没有值,fw.close会报错 FileWriter fw = null; try { //可能会产生异常的代码 fw = new FileWriter("W:\\environment\\java_project\\javase\\g.txt",true); for (int i = 0; i < 10; i++) { fw.write("HelloWorld"+i+"\r\n"); }}catch (IOException e){ //异常的处理逻辑 System.out.println(e); }finally { //一定会执行的代码 //创建对象失败了,fw的默认值是null,null不能调用方法,会抛出NullPointerException,需要增加一个判断,不是null再把资源释放 if (fw!=null){ try { //fw.close方法声明抛出了IOException异常对象,所以我们就得处理这个异常对象,要么throws,要么try...catch fw.close(); //Alt+Enter,使用try...catch } catch (IOException e) { e.printStackTrace(); } } } } }

  • JDK7的新特性
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; /* JDK7的新特性 在try的后边可以增加一个(),在括号中可以定义流对象 那么这个流对象的作用域就在try中有效 try中的代码执行完毕,会自动把流对象释放,不用写finally 格式: try(定义流对象;定义流对象...){ 可能会产出异常的代码 }catch(异常类变量 变量名){ 异常的处理逻辑 } */ public class Demo02JDK7 { public static void main(String[] args) { try (//1.创建一个字节输入流对象,构造方法中绑定要读取的数据流 FileInputStream fis = new FileInputStream("D:\\environment\\java_project\\javase\\c.txt"); //2.创建一个字节输出流对象,构造方法中绑定要写入的目的地 FileOutputStream fos = new FileOutputStream("D:\\environment\\java_project\\javase\\d.txt"); ){//可能会产生异常的代码 //一次读取一个字节写入一个字节的方式 //3.使用字节输入流对象中的方法read读取文件 int len = 0; while ((len = fis.read())!=-1){ //4.使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中 fos.write(len); } }catch (IOException e){ //异常的处理逻辑 System.out.println(e); } } }

  • JDK9的新特性(使用不便)
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; /* JDK9新特性 try的前边定义流对象 在try后边的()中可以直接引入流对象的名称(变量名) 在try代码执行完毕之后,流对象也可以释放掉,不用写finally 格式: A a = new A(); B b = new B(); try(a,b){ 可能会产出异常的代码 }catch(异常类变量 变量名){ 异常的处理逻辑 } */ public class Demo03JDK9 { public static void main(String[] args) throws IOException { //1.创建一个字节输入流对象,构造方法中绑定要读取的数据流 FileInputStream fis = new FileInputStream("D:\\environment\\java_project\\javase\\c.txt"); //2.创建一个字节输出流对象,构造方法中绑定要写入的目的地 FileOutputStream fos = new FileOutputStream("D:\\environment\\java_project\\javase\\d.txt"); try (fis; fos){ //一次读取一个字节写入一个字节的方式 //3.使用字节输入流对象中的方法read读取文件 int len = 0; while ((len = fis.read())!=-1){ //4.使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中 fos.write(len); } }catch (IOException e){ System.out.println(e); } fos.write(1); //Stream closed } }

    推荐阅读