异常、IO流

异常、IO流

1、异常

1、概念
     程序出现不正常的情况
2、异常体系
      Throwable
          |—Error                                    严重的错误,比如硬件坏了
          |—Exception                                   
                    |—RuntimeException     运行时异常,不需要处理,需要改代码
                    |—非RuntimeException  编译时异常,需要处理
     注意:
          每种体系的子类都是以父类的名称作为后缀
          XxxError
          XxxException
3、JAVA虚拟机的默认处理方式
     把异常的类名,原因,位置等信息显示在控制台
     一旦有异常发生,其后的代码不能继续执行
4、异常的解决方案
     A:自己处理
          基本格式
                try{
                    可能发生异常的代码;
               }catch(异常类名 变量名){
                    异常的处理代码;
               }finally{
                    释放资源的代码;
               }
          变形格式
               try..catch
               try..catch..catch
               try..catch..catch..finally
               try..finally
          注意:
               不能写成 try{}单独存在
         
          JDK1.7针对多个catch做了优化
               try{
                    可能发生的异常代码;
               }catch(异常1 | 异常2 | 异常3){//注意,这些异常必须是平级关系

               }finally{

              }
     B、声明异常
           用throws关键字在方法上声明异常
           注意:throws应该叫声明,有些人叫抛出,这么叫是不准确的
                     throw是抛出
5、到底应该选用谁?
          a、能自己处理的就自己处理
          b、不能自己处理的就抛出

2、final,finally,finalize 的区别
         final  用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。

          内部类要访问局部变量,局部变量必须定义成final类型

          finally是异常处理语句结构的一部分,表示总是执行。

          finalizeObject类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。JVM不保证 此方法总被调用

               b:finally  里面的代码永远会执行吗 ?
                    不一定,程序在执行fianlly前以外G掉
               c:  假如在catch里面有 ruturn,finally里面的代码还能被执行吗 ?
                    如果能 , 请问是在  return ,  还是在 return   ?
请看下面程序代码的运行结果:

     static int test() {

          int x = 1;

          try

          {

              return x;

          }

          finally

          {

              ++x;

          }

     }

---------执行结果 ---------

运行结果是1,为什么呢?主函数调用子函数并得到结果的过程,好比主函数准备一个空罐子,当子函数要返回结果时,先把结果放在罐子里,然后再将程序逻辑返回到主函数。所谓返回,就是子函数说,我不运行了,你主函数继续运行吧,这没什么结果可言,结果是在说这话之前放进罐子里的。

 2、ExceptionRuntimeException 的区别?
           A:Exception  编译时期异常,必须处理的。
                      如果在方法上,  throws 了该类型的异常,将来调用者必须处理。
                      如果在方法内部,  throw 了该类型的异常,必须在方法上  throws 该异常。
           B:RuntimeException  运行时期异常,是不需要处理的。要改代码的。
                      如果在方法上,  throws 了该类型的异常,不需要处理。
                      如果在方法内部,  throw 了该类型的异常,方法上可以  throws 该异常,也可以不 throws 该异常。
3、throwthrows 的用法和区别 ?
           A:throw
                   用法:用在方法内部,后面跟的是异常对象名称。
                   区别:用  throw 抛出了编译时期异常,方法上面必须用  throws 抛出。
                        throw 抛出了运行时期异常,方法上面可以不用  throws 抛出。
           B:throws
                   用法:用在方法声明上,后面跟的是异常类名。
                   区别:用  throws 在方法上声明了异常,内部可以没有  throw

3、File类

 1、概述
               因为数据在硬盘上最常见的方式,就是文件。而文件本身有很多的属性,比如说:文件大小,是否可读,是否隐藏。那么  java 为了方便我们对文件进行操作,就提供了  File 类供我们使用。
              File 既可以表示文件,也可以表示  ( 目录 )  文件夹。   
               

4、File类-成员方法

构造方法

File(String pathName)

根据指定的路径创建File对象

File(String parent, String child)

根据指定的父文件夹和子文件或者文件夹创建File对象

File(File parent, String child) 

根据指定的父文件夹对象和子文件或文件夹创建File对象

以上三个方法,创建当前文件或文件夹的时候都是先看是否存在,如果存在就不创建,否则就创建

创建功能

boolean createNewFile()

创建文件

boolean mkdir()

创建文件夹

boolean mkdirs()

创建多级文件夹

删除功能

public boolean delete() 

删除文件或文件夹

A:如果删除的目录下还有内容,则必须先把该目录下的的内容清空

BJAVA语言的删除不走回收站

判断功能

public boolean exists()

判断 file 对象是否存在

public boolean isFile()

判断 file对象是否是文件

public boolean isDirectory()

判断 file对象是否是文件夹

public boolean isAbsolute()

判断 file对象是否是绝对路径

 public boolean canRead()

判断 file对象是否可读

public boolean canWrite()

判断 file对象是否可写

public boolean isHidden()

判断 file对象是否隐藏

获取功能

public File getAbsoluteFile()

获取文件的绝对路径

public String getName()

获取文件名称

public String getPath()

获取相对路径

public long length()

获取文件的大小,单位是字节

public long lastModified()

获取上次修改时间的毫秒值

public static File[] listRoots()

列出可用的系统文件根目录

public String[] list()

 返回的是指定目录下所有文件或者文件夹的名称数组

 public String[] list(FilenameFilter filter)

public File[] listFiles()

返回的是指定目录下所有文件或者文件夹对象数组

public File[] listFiles(FilenameFilter filter)

 

5、File类-案例

1、获取指定目录下所有 .mp4文件的名称

importjava.io.File;

importjava.io.FilenameFilter;

/*

 * 获取指定目录下指定后缀的文件名称:

 * A:先获取指定目录下所有文件或者文件夹的File数组,然后再遍历的时候进行判断。满足条件的就输出该File的名称。

 * B:直接获取指定目录下满足条件的String(File)数组。然后遍历数组即可。

 *

 * 文件名称过滤器:FilenameFilter

 *        public String[] list(FilenameFilter filter)

 */

public classFileDemo {

      public static voidmain(String[] args) {

           // 封装目录

           File file = new File("d:\\");

 

           // 获取满足条件的数组

           String[] strArray = file.list(new FilenameFilter() {

                 @Override

                 public booleanaccept(File dir, String name) {

                      // 判断是否是文件,是否是以.mp4结尾

                      // System.out.println(dir + "---" + name);

                      File file = new File(dir, name); // d:\我的文档

                      boolean flag = file.isFile();

                      boolean flag2 = name.endsWith(".mp4");

                      return flag && flag2;

                 }

           });

 

           // 遍历字符串数组

           for(String str : strArray) {

                 System.out.println(str);

           }

      }

}

 



6、递归

1、概述
     方法定义中调用方法本身的现象
2、注意事项
     A、递归次数不能过多,否则内存溢出
     B、一定要有出口,否则死递归。
     C、构造方法不能递归
3、递归案例
     A、求N的阶乘
               public static int jc(int n){
     if(n ==1){
          return 1;
     else 
          return n* jc(n -1);
     }
               }
     B、递归遍历指定目录,列出文件和文件夹的绝对路径
     C、递归删除带内容目录

7、IO体系



8、FileWriter

1、使用步骤

/**

 * FileWriter类的使用

 * 该类是写入字符文件的快捷类

 */

public classFileWriterDemo {

       public static voidmain(String[] args)throws Exception {

              //第一步:创建字符流输出对象

              FileWriter fw = new FileWriter("readme.txt");

             

              //第二步:调用写入数据方法

              fw.write("注意事项"+System.getProperty("line.separator"));

              fw.write("1、上课不能玩手机"+System.getProperty("line.separator"));

              fw.write("2、不能迟到早退"+System.getProperty("line.separator"));

             

              //第三步:调用刷新缓冲区功能,该功能会将缓冲区的数据写入到文件,并且清空缓冲区中的内容

              fw.flush();

             

              //第四步:关闭流,释放资源

              fw.close();

       }

}

2、flush 方法和close方法的区别
     flush只刷新缓冲区,不释放流资源,流对象还可以继续使用
     close刷新并且释放流资源,流对象不可以继续使用
3、如何实现数据换行
     window:\r\n
     linux:\n
     mac:\r
     通用解决方案:String line = System.getProperty("line.separator");//根据当前系统返回相应的换行符
4、怎么实现追加数据
     调用FileWriter(String fileName, true)构造方法创建对象 

9、FileReader

1、使用步骤

importjava.io.FileReader;

public classFileReaderDemo {

       public static voidmain(String[] args)throws Exception {

              //第一步:创建字符流输入对象

              FileReader fr = new FileReader("readme.txt");

            

              //第二步:调用读取数据方法,并显示

              /*

               *方式1::一次读取一个字符,效率低 ,不推荐

               */

              int ch = 0;

              while((ch=fr.read()) != -1){

                     System.out.print((char)ch);

              }

             

             

              /*

               * 方式2:一次读取一个字符数组,效率高推荐

               */

              fr = newFileReader("readme.txt");//必须重新赋值,或者注释掉方式1中的代码,因为fr对象已经读取到末尾了,必须重新开始读取

              char[] chs = new char[1024];

              int len = 0;

              while((len = fr.read(chs)) != -1){

                     System.out.println(newString(chs,0,len));

              }

             

              //第三步:关闭流,释放资源,该对象无法继续使用

              fr.close();

       }

      

}

 



10、例子

1、复制文本文件 , D 盘中复制一个 haha.txt文件( 里面字节写上 我爱学Java, 我爱学编程 ”)E 盘下, 起名为 copy.txt
try异常的代码

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

 

 

public class CopyFileDemo {

 

       public static void main(String[] args) throws Exception {

              boolean flag = copy(new FileReader("D://haha.txt"), new FileWriter("E://haha.txt"));

              if(flag){

                     System.out.println("拷贝成功");

              }else{

                     System.out.println("拷贝失败");

              }

       }

       /**

        * 拷贝文件

        * 思路:读取文件内容的同时,将读取到的内容写入到输出流

        */

       public static boolean copy(FileReader fileReader, FileWriter fileWriter) {

              //标识符,拷贝成功变为true并返回,拷贝失败返回false

              boolean flag = false;

             

              //创建字符数组,将读取到的内容存进去

              char[] chs = new char[1024];

              int len = -1;

             

             

              try {

                     //读取文件,将读取到的内容存到chs字符数组

                     while((len = fileReader.read(chs)) != -1){

                            //将字符数组中的内容写入到输出流

                            fileWriter.write(chs, 0, len);

                            fileWriter.flush();

                     }

                    

                     //拷贝成功,修改标识符的值为true

                     flag = true;

              } catch (IOException e) {

                     e.printStackTrace();

              }finally{

                     try {

                            fileWriter.close();

                     } catch (IOException e) {

                            e.printStackTrace();

                     }

                     try {

                            fileReader.close();

                     } catch (IOException e) {

                            e.printStackTrace();

                     }

              }

             

             

              return flag;

       }

}

 

抛异常的代码
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class FileUtil {
         /**
          *  拷贝文本文件
          *  src  拷贝到  dest
          * @param src
          *  源文件
          * @param dest
          *  目标文件
          */
         public static void copy(File src, File dest) throws IOException {
                   FileReader fr =new FileReader(src);
                   FileWriter fw = new FileWriter(dest);

                   
                   char[] chs = new char[1024];
                   int len = -1;
                   while ((len = fr.read(chs)) != -1) {
                            fw.write(chs, 0, len);
                   }
                   
                   fr.close();
                   fw.close();

         }
}


11、字节流 与 字符流 比较

1、到底使用谁
     如果在写数据的时候需要另起一行或者读数据的时候一行一行读就用字符缓冲流:BufferedReader & BufferedWriter
     如果操作的是文本就用字符流,因为操作比较方便。否则就用字节流
     如果根本不知道用哪个,就用字节流,因为字节流很强大
2、复制文本文件
     (1)复制文本文件的几种方式
          字节流:
                      4 
                              基本流一次读写一个字节
                              基本流一次读写一个字节数组
                              高效流一次读写一个字节
                              高效流一次读写一个字节数组
                   字符流:
                      5 
                              基本流一次读写一个字符
                              基本流一次读写一个字符数组
                              高效流一次读写一个字符
                              高效流一次读写一个字符数组
                              高效流一次读写一个字符串
     (2)推荐
          既然是文本文件那么用字符串缓冲流读写是最好的方式
     (3)推荐代码:

public static void main(String[] args) throwsException{

              //字符缓冲输入流

              BufferedReader bufferedReader = new BufferedReader(newFileReader("d://readme.txt"));

              //字符缓冲输出流

              BufferedWriter bufferedWriter = new BufferedWriter(newFileWriter("d://readme.txt.bak"));

             

              String line = null;

              //每次读取一行,如果读到null就停止读取文件内容

              while((line=bufferedReader.readLine()) != null){

                     bufferedWriter.write(line);

                     bufferedWriter.flush();

              }

             

              //关闭流

              bufferedReader.close();

              bufferedWriter.close();

       }

3、复制二进制数据(非文本文件,音乐,视频,应用软件等..)
      (1)赋值二进制文件的几种方式
                   基本流一次读写一个字节
                   基本流一次读写一个字节数组
                   高效流一次读写一个字节
                   高效流一次读写一个字节数组
       (2)推荐
          使用缓冲流一次读写一个字节数组
      (3)推荐代码

       public static voidmain(String[] args) throws Exception {

              // 定义字节缓冲输入流

              BufferedInputStream bis = null;

              // 定义字节缓冲输出流

              BufferedOutputStream bos = null;

 

              try {

                     bis = new BufferedInputStream(newFileInputStream("d://readme.txt"));

                     bos = new BufferedOutputStream(newFileOutputStream("d://readme.txt.byte"));

                     byte[] bys = new byte[1024];

                     int len = -1;

 

                     while ((len = bis.read(bys)) != -1) {

                            bos.write(bys, 0, len);

                            bos.flush();

                     }

              } catch(Exception e) {

                     e.printStackTrace();

              } finally {

 

                     if (bis != null) {

                            try {

                                   bis.close();

                            } catch (Exception e) {

                                   e.printStackTrace();

                            }

                     }

 

                     if (bos != null) {

                            try {

                                   bos.close();

                            } catch (Exception e) {

                                   e.printStackTrace();

                            }

                     }

                     // 关闭流

              }

       }



12、Properties

1、概述
     Properties是一个键值对的 集合类,不是IO类键和值都是字符串。可以从流中加载数据或者把数据保存到流中,是唯一一个可以和IO流集合使用的集合类
添加修改
public Object put(Object key, Object value)
添加修改
public Object setProperty(String key,String value)
调用的就是  put 方法
获取功能
public String get(String key)
获取
Public String getProperty(String key)
底层调用的是  get
Public String getProperty(String, String defaultValue)
底层调用  get, 如果找不到,返回  defaultValue
public Set<String> stringPropertyNames()
获取键集合
转换功能
public void list(PrintWriter out)
将属性列表输出到指定的输出流 
 
public void list(PrintStream out)
public void load(InputStream inputStream)
从输入流中读取属性和列表
public void load(Reader reader)
public void store(OutputStream out, String comment)
把集合中的数据保存到文本中
public void store(Writer writer, String comments)
public Set keySet()
获取所有键的集合
 
注意:Properties类在以后Android中会有新的Properties替代,在EE中我们会重新封装一个Properties工具类,因为Properties的缺点很明显,不能直接操作File对象

13、System类

1、系统类,提供了静态的变量和方法供我们使用
2、成员方法

public static void exit(int value)

退出jvm,非0表示异常退出

public static long currentTimeMillis()

返回当前系统时间的毫秒值

public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)

从指定源数的指定位置开始复制,赋值到目标数组的指定位置

public static Properties getProperties();

获取当前系统的属性

public static String getProperty(String key)

获取指定键描述的系统属性

public static String getProperty(String key, String defaultValue)

获取指定键描述的系统属性,没有找到该键的话返回defaultValue


遍历Properties 

       /**

        * 遍历系统描述Properties

        */

        public static voidmain(String[] args) throws Exception{

              Properties properties = System.getProperties();

              Set<Object> keySet = properties.keySet();

              for(Object key:keySet){

                     System.out.println(key +"*****"+properties.get(key));

              }

       }



获取当前系统中的换行符

/**

        * 获取当前系统中的换行符

        */

        public static voidmain(String[] args) throws Exception{

               String line = System.getProperty("line.separator");

               System.out.println(line+"你好");

       }


14、转换流

1、为什么要用转换流?
      因为从控制台获取数据时获取到的是字节流,但是我们输入的是字符,所以操作字符流会更加方便,这时就需要转换流
     转换流就是字符流和字节流之间的一个桥梁,别人给你一个字节流,明知道里面存的是文本,用字符流操作更方便,所以就要用转换流
2、记忆原则:
       最终目的是要使用字符流,所以
      第一步:先new一个字符流,这是我们要直接调用的
      第二部:new一个转换流传给字符流,这是中间流
      第三部:把字节流传给转换流,这是要转换的流

              /*输入转换流演示*/

//System.in 是个输入流,可以看成FileInputStream

              BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

              String line = reader.readLine();

              System.out.println(line);

              reader.close();

             

             /*输出转换流演示*/

              //System.out 是个字节输出流,这里看成 new FileOutputStream();就可以了

              BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));

              writer.write("你好");

              writer.flush();

              writer.close();


2、转换流编码问题
     读取转换流和写入转换流都有带参的构造,可以指定编码,可以设置以何种编码读取字节或写入字节
     InputStreamReader(InputStream in, String charsetName)
     OutputStreamWriter(OutputStream, out, String charsetName)
     

              /*输入转换流演示*/

//System.in 是个输入流,可以看成FileInputStream

              BufferedReader reader = new BufferedReader(new InputStreamReader(System.in,"UTF-8"));

              String line = reader.readLine();

              System.out.println(line);

              reader.close();      

 

              /*输出转换流演示*/

              //System.out 是个字节输出流,这里看成 new FileOutputStream();就可以了

              BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out,"UTF-8"));

              writer.write("你好");

              writer.flush();

              writer.close();


15、打印流

1、特点
     A、可以写入任意类型数据
     B、可以自动刷新。必须先启动,并且是使用println,print,format方法才有效
     C、可以直接对文件进行写入

2、注意事项
     打印流只能输出数据,不能读取数据换句话说就是只能操作数据目的能操作数据源

3、PrintWriter 和 PrintStream的区别
     1、PrintWriter构造方法可以传入输出字符流,而PrintStream不可以
     2、PrintWriter主要用于操作字符流,PrintStream主要用于操作字节流
     3、PrintWriter想要实现自动刷新构造方法必须手动指定,而PrintStream则不需要手动指定
     4、PrintWriter继承自Writer,PrintStream继承自FileOutPutStream
4、使用
A、PrintWriter的使用方式
          1、通过构造方法创建对象并且启用自动刷新功能
                    PrintWriter(OutputStrem out, boolean autoFlush);
                    PrintWriter(Writer out, boolean autoFlush);
          2、调用println\printf\format方法,只有调用这三个个方法才会自动调用flush方法

PrintWriter printWriter = newPrintWriter(new FileWriter("d.txt"),true);

printWriter.printf("1");//仅仅写入数据并且刷新

printWriter.println("2");//写入数据并且增加换行符,刷新

printWriter.format("你好 %s", "张三");



          B、PrintStream的使用方式
                     1、通过构造方法创建对象并且启用自动刷新功能
                              PrintStream(OutputStrem out, boolean autoFlush);
                    2、调用println\printf\format方法,只有调用这三个个方法才会自动调用flush方法

PrintStream ps = newPrintStream(new FileOutputStream("a.txt"),true);//,true可有可无

ps.printf("你好");

               

16、序列化

1、概述
     通俗点理解序列化就是把内存中的对象写到硬盘上

2、友情提示
     开发中习惯给实体类实现Serializable接口,但是ObjectInputStream和ObjectOutputStream一般不用,因为有时候我们需要序列化JDK自带的类,但是这些类有可能没有实现该接口,所以开发中我们通过XML序列化,但是我们还是要实现该接口,不能保证永远不用

3、如果一个类想被序列化流操作就要实现Serializable接口
     如果实现了该接口,想解决黄线问题就生成一个随机的serialVersionUID号码



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值