首页 > 代码库 > 黑马程序员_IO流1
黑马程序员_IO流1
异常
1、异常的继承体系:
java.lang.Throwable类,所有异常和错误的父类
Error类所有错误的父类
Exception类所有异常的父类
RuntimeException
NullPointerException
ClassCastException
IndexOutOfBoundsException
错误,比较严重的问题,一旦出现了错误,程序根本不能运行,必须修改源代码。
异常,比较轻微的问题,一旦出现了异常,程序可以处理掉异常,继续运行。异常一般是程序的最后一个问题。
2、Throwable类
构造方法 Throwable(String message)异常信息
String getMessage()返回异常信息的详细字符串
String toString()返回异常信息的简短描述
void printStackTrace()将异常信息直接输出在控制台
3、异常的第一种处理方式
try catch 代码块处理
标准格式:
try{
被检测的代码,可能出现异常的代码
}catch(异常类 变量){
异常的处理方式
变量.调用Throwable类的三个方法
}
4、异常的第二种处理方式抛出异常
如果程序运行的时候,由于用户或者调用非法传递参数,导致程序出现问题,假如调用者真的传递了非法的数据,需要手动抛出异常。在方法中,使用关键字throw 写异常对象,new 出来 的.如果一直一层层的往外抛异常,直到抛给JVM。这样真的发生了问题,程序就会停止运行。所以不建议一直往外抛。
5、throw 和throws的区别:
throw 写在方法内部,后面必须希望new 异常();
throws 写在方法的声明上,后面必须写异常类名。
6、编译时期异常和运行时期异常
编译时期异常:调用了一个抛出异常的方法,不处理,编译失败
运行时期异常:RuntimeException类和他所有的子类都属于运行时期异常
特点:如果方法内部用throw 抛出的是一个运行时期异常,此时方法声明上,不需要使用throws声明异常,调用者不需要处理这个异常,Java工程师们设计运行时异常的初衷,运行时期异常一 旦发生,程序必须停下来修改源代码。
7、自定义的异常
Java原有异常体系中,很多的现象进行异常的封装,越界,类型转换,JDK中也有想不到的异常,所以自定义异常
第一步,入伙 。继承 Exception 或者继承RuntimeException
第二步,传递异常信息,将异常信息传递给Exception的构造方法
注意:异常必须是Exception或者RuntimeException的子类
class MyException extends RuntimeException{ MyException(String message){ super(message); }}
8、finally代码块
try{} catch(Exception e){} finally{}
try{} finally{}
finally代码块中的程序,必须要执行,不管程序有没有异常方法,finally中的程序必须执行
注:finally代码块中不能放返回值语句,否则前面的都没有意义。
finally的用处:
用于释放资源
9、子类继承父类后的异常细节:
父类不抛,子类不能抛;
父类抛了,子类可抛可不抛;子类如果抛了,那么异常的类型不能超过父类;
方法中可以抛多个异常,但如果抛出的是编译时期的异常,需要声明,而且调用者要写多个catch处理;
多catch处理中,最高异常放最后面。但一般不使用带子父类关系的异常。
IO流
1、IO中的继承体系
字符输出流,写文本文件的,抽象基类 java.io.Writer,写文件的,写的方法有:
write(字符数组) write(字符数组一部分) write(单个字符) write(字符串)
字符输入流,读文本文件的,抽象基类 java.io.Reader,读文件的,读的方法有
read()单个字符 read(字符数组) read(字符数组一部分)
字节输出流,写任意文件的,抽象基类 java.io.OutputStream,写文件的,写的方法
write(单个字节) write(字节数组) write(字节数组一部分)
字节输入流,读任意文件的,抽象基类 java,io.InputStream,读文件的,读的方法
read()单个字节 read(字节数组) read(字节数组一部分)
字符流
1、字符输出流写文本文件
字符输出流 父类Writer不能直接使用,所以找子类FileWriter类
构造方法 FileWriter(字符串的文件名)
字符流在写数据的时候,write方法写,数据写在了内存中,并没有直接写到目的文件中。如果让数据写到目的文件中,字符流要进行缓存区的刷新操作。Writer中的方法flush,刷新流的缓 冲,将数据写到目的地。
文件的续写,文件的后面追加写入,原有的数据都被保留下来
FileWriter类构造方法中,传递String的文件名,true实现追加写入
2、字符输入流读文本文件
Reader类是抽象类,找子类FileReader
构造方法 FileReader(字符串文件名)
FileReader调用父类方法实现读取功能
A.读取单个字符的方法
int read() 读取一个字符
read()方法,每次只能读取一个字符,返回这个字符的码值,每调用一次read()自动向后读取一个字符,如果读取到文件的末尾,返回-1。
注意:文件读取的时候,一次循环不允许出现2次read()
保证读取的文件必须是GBK编码的(ANSI)
B.读取字符数组 int read(char[] ch),每次读取到的字符,装在字符数组中,返回每次读取的有效字符个数
3、字符输出流的缓冲区对象
数组的缓冲,提高了流对象的读写效率,开发出现流对象的缓冲区对象,目的提高流的操作效率。字符输出流的缓冲区 java.io.BufferedWriter
字符输出流缓冲区对象方法:
构造方法 BufferedWriter(Writer out)传递的是Writer的子类对象
void newLine()写一个换行。此方法具有跨平台性,\r\n Windows下有效,Linux操作系统\n
4、字符输入流的缓冲区对象 java.io.BufferedReader
字符输入流缓冲区对象的方法
构造方法 BufferedReader(Reader in),传递是的Reader类的子类对象
String readLine()读取文本一行,返回字符串,读取文件结尾,返回null,读取一行,返回的字符串中,没有\r\n符号,返回是一行有效字符
5、用字符流复制文本的三种方式:
A、字符流对象完成,读一个,写一个
1 package cn.itcast.iostream; 2 /* 3 * 复制文本文件:字符流对象完成,读一个字符,写一个字符 4 * 实现步骤: 5 * 1. FileReader建立对象,包装源文件 c:\a.html 6 * 2. FileWriter建立对象,包装目的文件 d:\a.html 7 * 3. read方法读取一个字符 8 * 4. write方法写一个字符,刷新 9 * 5. 关闭资源10 */11 import java.io.*;12 public class CopyText {13 public static void main(String[] args) {14 //建立两个流对象15 FileReader fr = null;16 FileWriter fw = null;17 try{18 fw = new FileWriter("d:\\w.log");//数据目的19 fr = new FileReader("c:\\w.log");//数据源20 //开始循环读取源文件,读一个字符写一个字符21 int len = 0 ;22 while((len = fr.read())!=-1){23 fw.write(len);24 fw.flush();25 }26 }catch(IOException e){27 //输出异常信息28 e.printStackTrace();29 throw new RuntimeException("复制失败");30 }finally{31 try{32 if(fr!=null)33 fr.close();34 }catch(IOException e){35 throw new RuntimeException("读取源关闭失败");36 }finally{37 try{38 if(fw!=null)39 fw.close();40 }catch(IOException e){41 throw new RuntimeException("文件写入关闭失败");42 }43 }44 }45 }46 }
B.读取字符数组 int read(char[] ch),每次读取到的字符,装在字符数组中,返回每次读取的有效字符个数
1 char[] buf = new char[1024];2 int len = 0 ;3 while((len = fr.read(buf))!=-1){4 fw.write(buf,0,len);5 fw.flush();6 }
C.利用字符流的缓冲区对象。增加了读取行的功能。读一行写一行
bfr = new BufferedReader(new FileReader("c:\\c.txt"));
bfw = new BufferedWriter(new FileWriter("d:\\c.txt"));
String line = null;
// 循环读取文件,行读和写
while((line = bfr.readLine())!= null){
bfw.write(line);
bfw.newLine();
bfw.flush();
}
字节流
1、字节输出流
字节可以操作任意文件,字节输出流,写任意文件,单个字节8个二进制。 不查询编码表。
字节输出流的抽象基类OutputStream
写的方法:写字节数组,字节数组一部分,单个字节
子类FileOutputStream类,文件的输出
字节流写数据,不需要刷新,直接向数据写到目的地
2、字节输入流
字节可以操作任意文件,字节输入流读取文件,单个字节8个二进制
字节输入流的抽象基类InputStream
读取的方法:读取单个字节,读取字节数组,读取字节数组一部分
子类是FileInputStream,构造方法直接传递字符串文件名
读取单个字节的read()方法,返回字节的码值,文件末尾返回-1
int available()返回字节输入流封装的文件的字节数
3、字节流复制文件的方法:和字符流的复制方法相似
第一种方式读取一个字节,写一个字节
第二种方式读取一个字节数组,写一个字节数组--重点案例,必须要写熟练
import java.io.*;public class CopyFile2 { public static void main(String[] args) { long start = System.currentTimeMillis(); FileInputStream fis = null; FileOutputStream fos = null; try{ fis = new FileInputStream("c:\\1.avi"); fos = new FileOutputStream("d:\\1.avi"); int len = 0 ; byte[] bytes = new byte[1024]; while((len = fis.read(bytes))!=-1){ fos.write(bytes,0,len); } }catch(IOException e){ e.printStackTrace(); throw new RuntimeException("复制失败"); }finally{ try{ if(fos!=null) fos.close(); }catch(IOException e){ throw new RuntimeException("文件写入关闭失败"); }finally{ try{ if(fis!=null) fis.close(); }catch(IOException e){ throw new RuntimeException("文件读取关闭失败"); } } } long end = System.currentTimeMillis(); System.out.println(end - start); }}
第三种方式读取文件,用字节流缓冲区实现
注:所有的read方法readLine方法,等待效果,线程阻塞.
转换流
1、 InputStreamReader
System类的静态成员变量 public static final InputStream in;返回的字节输入流对象,这个对象是JVM底层自带的一个字节输入流,它的父类是InputStream.
InputStreamReader是Reader的子类,字符流对象,字节流向字符的桥梁。InputStreamReader有一个子类就是FileReader
InputStreamReader构造方法:InputStreamReader(InputStream in)传递字节输入流,变成字符流
2、OutputStreamWriter
System类的静态成员变量 public static final PrintStream out;返回打印流对象PrintStream,也是OutputStream的子类
OutputStreamWriter是Writer的子类,字符流对象,字符流向字节的桥梁
OutputStreamWriter构造方法,OutputStreamWriter(OutputStream out)传递的是字节输出流
3、转换流的案例
/**从键盘输入,转为大写,再从控制台输出*/ public static void main(String[] a) throws IOException { BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(System.out)); String line = null; while ((line = bfr.readLine()) != null) { if ("over".equals(line)) break; bfw.write(line.toUpperCase()); bfw.newLine(); bfw.flush(); } bfw.close(); bfr.close(); }
注:转换流只能用来操作文本文件。因为InputStreamReader和OutputStreamWriter都是字符流。
他们传递的参数都是字节流,但是他们的流向不同,一个输出,一个输入。
编码表
1、常见的编码表:
每一个字符,在编码中,对应一个十进制数,十进制转为二进制就能被计算机 识别了。
ASCII 美国标准信息交换码 内面只有 符号,数字,字母(大小写区别)的编码
GBK,在ASCII基础上加入了汉字,汉字对应二个十进制数
Unicode 万国码
现在使用的UTF-8中,汉字是三个字节
ISO8859-1 拉丁文。
2、在转换流对象中,可以指定编码表
转换流对象,构造方法,第一个参数是字节流,第二个参数可写编码表的名字
注:若编码表为GBk,可以不写。
3、乱码和???
??? 不是乱码,编码表中,没有查到任何数据
獾才: 编码表中查到的结果
注:以后做程序,如果发生乱码或者???现象,是由于采用的编码表不一致造成的
4、字符的编码和解码
将一个字符串转成字节数组,称为字符的编码 String类的方法getBytes
getBytes()还有一个重载函数:byte[] getBytes(编码表)
将字节数组还原会字符串,成为字符的解码 String类的构造方法
String同样有一个重载构造函数String(byte[] bytes ,编码表)
1 public class CharEncoding { 2 public static void main(String[] args)throws Exception { 3 //method(); 4 //method_1(); 5 byte[] bytes= "琲".getBytes(); 6 for(byte b : bytes){ 7 System.out.println(b); 8 } 9 }10 //将字符串你好,转成字节数组,查询UTF-811 public static void method_1() throws Exception{12 byte[] bytes = "你好".getBytes("utf-8");13 for(byte b : bytes){14 System.out.println(b);15 }16 byte[] bytes2 = {-28,-67,-96,-27,-91,-67};17 System.out.println(new String(bytes2,"utf-8"));18 }19 20 //将字符串,你好,转成字节数组21 public static void method(){22 byte[] bytes = "你好".getBytes();23 //将你好两个字,进行编码表的查询GBK,将汉字对应的十进制数,存储到字节数组24 for(byte b : bytes){25 System.out.println(b);26 }27 28 byte[] bytes2 = {-60,-29,-70,-61};29 String s = new String(bytes2);30 System.out.println(s);31 }32 }