java - day012 - 异常 , throws, throw , IO ,RandomAccessFile

  • 异常 封装错误信息的对象
    • 错误信息
    1. 类型        例如: NullPointerExce 空指针
    2. 提示消息 
    3. 出错的行号
  • 异常的继承结构
    • Throwable
    1. | - Error 系统级错误
    2. | - Exception 可修复的错误
      • | - 其他Exception
      • | - RuntimeException
        • | - NullPointException 空指针
        • | - ArrayIndecOutOfBoundException  1  数组下标1越界
        • | - ArithmeticException 数学异常 
        • | - NumberFprmatException 数字格式异常
        • | - ClassCastException

 

  • 异常的处理流程
    • 程序错误 , 封装成异常对象 , 抛出异常
    • 如果没有捕获异常的处理
      • 会被JVM 虚拟机接收打印异常信息,并关闭虚拟机

 

  • 异常的捕获
  • try{
    
    }catch(AException e){// 捕获 A 类型异常
    
    }catch(BException e){// 捕获 B 类型异常

    }catch(父类型异常 Exception e){如果有父类型放在最后
    // 放在第一位,只会执行此异常类型,不会执行其异常类型
    }finally{
    // 不管出错不出错,都会被执行
    // 一般用来清理一些资源
    }
  • throws
    • 设置异常的抛出管道
    • 方法中要抛出异常, 必须存在对应类的抛出管道
    • 在任何方法上都有默认的异常管道: RuntimeException 
    • RuntimeException 及其子类异常,都可以从默认管道抛出
    • 不是RuntimeException类型的异常必须写对应的异常抛出管道
    • private static void f() throws ParseException, IOException {

      }

       

 

  •  RuntimeException 及其子类型都有默认的抛出管道
    • 非检查异常,编译器编译代码时, 不会检查RuntimeException异常
    • 检查异常 (非 RuntimeException )
      • 编辑器编辑代码是, 会检查是否捕获异常或添加了管道
      • 都没有,会编译失败

 

  • throw
    • 手动抛出异常
    • 执行异常的抛出动作
    •                if (b == 0) {
      			// 新建异常对象, 括号里面可以添加错误信息字符串
      			ArithmeticException e = 
      					new ArithmeticException("不能除0");
      			// 抛出异常到调用位置
      			throw e;
      		}
      

       

 

  • 异常包装
    • 捕获的异常,包装成其他有抛出管道类型,再抛出
    • 使用场景
      • 不能抛出的异常,包装成能抛出的异常类型再抛
      • 异常简化,减少异常管道数量
    • 重写方法的异常管道, 不能比父类方法异常管道多,且不能不同于父类的异常管道
    •         
              Collections.sort(list, new Comparator<String>() {
      
                  @Override
                  public int compare(String o1, String o2) {
                      
                      try {
                          SimpleDateFormat sdf = 
                                  new SimpleDateFormat("yyy-MM-dd");
                          Date d1 = sdf.parse(o1);
                          Date d2 = sdf.parse(o2);
                          return d1.compareTo(d2);
                      } catch (ParseException e) {
                          // TODO Auto-generated catch block
                          throw new RuntimeException(e);
                      }
                              
                  }
                  
              });

       

 

  • 自定义异常
    • 继承RuntimeException 不用写异常管道
    • 继承Exception 需要写异常管道
    • 使用
      • 起一个合适的类名, 见名知意
      • 选择一个合适的父类,一般用Exception,RuntimeException
      • 添加合适的构造方法
    • /*
       * 继承 Exception 需要写异常管道抛出
       */
      public class UserNameNotFoundException extends Exception {
      
          public UserNameNotFoundException() {
              super();
              // TODO Auto-generated constructor stub
          }
      
          public UserNameNotFoundException(String message, Throwable cause, boolean enableSuppression,
                  boolean writableStackTrace) {
              super(message, cause, enableSuppression, writableStackTrace);
              // TODO Auto-generated constructor stub
          }
      
          public UserNameNotFoundException(String message, Throwable cause) {
              super(message, cause);
              // TODO Auto-generated constructor stub
          }
      
          public UserNameNotFoundException(String message) {
              super(message);
              // TODO Auto-generated constructor stub
          }
      
          public UserNameNotFoundException(Throwable cause) {
              super(cause);
              // TODO Auto-generated constructor stub
          }
          
      }



      // 使用
      public class Test1 {
          public static void main(String[] args) {
      
              System.out.println("输入用户名和密码");
              String n = new Scanner(System.in).nextLine();
              
              System.out.println("密码");
              String p = new Scanner(System.in).nextLine();
              
              try {
                  login(n,p);
                  System.out.println("欢迎登陆");
              } catch (UserNameNotFoundException e) {
                  System.out.println("用户名不存在");
              }catch (WrongPasswordException e) {
                  System.out.println("密码错误");
              }
          }
      
          private static void login(String n, String p) throws UserNameNotFoundException, WrongPasswordException {
              
              if (!n.equals("abc")) {
                  throw new UserNameNotFoundException();
              }
              
              if (!p.equals("123")) {
                  throw new WrongPasswordException();
              }
              
          }
      }
      
      

       

       

       


 

 

  • IO  input output (输入输出)
  • Java.io 包
    • File
    • RandomAccessFile
    • InputStream/OutputStream
    • FileInputStream/FileOutStream
    • BufferedInputStream/BufferedOutputStream
    • ObjectInputStream/ObjectOutputStream
    • Reader/Writer
    • IputStreamReader/OutputStreamWrite

 

  • File    封装磁盘路径字符串
    • 文件路径
    • 文件夹路径
    • 不存在的路径
    • 作用
      • 可以获得文件或者文件夹的属性
        • length(); 文件字节量,对文件夹无效
        • lastModified(); 最后修改时间, 毫秒值
        • getName(); 文件名
        • getParent(); 父目录
        • getAbsolutePath();磁盘完整路径
        • isExists(); 是否存在
        • isFile();是否是文件
        • isDirectory();是否是文件夹
        •         //path = "/Users/dingzhijie/Desktop/ceshi.txt"; // 存在的文件
                  //path = "/Users/dingzhijie/Desktop/ceshi222"; // 存在的文件夹
                  path = "d:dgv"; // 不存在的路径
                  
                  File file  = new File(path);
                  System.out.println(path);
                          
                  System.out.println(file.exists());
                  System.out.println(file.length());
                  System.out.println(file.isFile());
                  System.out.println(file.isDirectory());

           

      • 可以创建删除文件和文件夹
        • creatNewFile();创建文件,
          • 必须保证创建文件的文件夹是存在的
        • mkdirs();创建多层文件夹
        • delete();删除文件,或者空文件夹
        •         // 创建文件夹
                  File dir = 
                   new File("/Users/dingzhijie/Desktop/ccc");
                  if (!dir.isDirectory()) {
                      dir.mkdirs();
                  }
                  
                  
                  // 创建文件
                  File file = 
                   new File("/Users/dingzhijie/Desktop/cc.txt");
                  if (!file.isFile()) {
                      file.createNewFile();
                  }
                  
                  
                  
                  // 删除文件夹
                  if (dir.exists()) {
                      dir.delete();
                  }
                  
                  
                  // 删除文件
                  if (file.exists()) {
                      file.delete();
                  }

           

        • File.creatTempFile();创建临时文件(静态方法)
          • 系统资源紧张的时候,或者管家也会清理临时文件
          • \Users\wanght\AppData\Local\Temp
        •        /*
                   * 参数: 前缀, 至少三个字符
                   * 参数: 后缀, 可以不写  null 会自动添加
                   */
                  File file = 
                          File.createTempFile("abc", ".txt");
                  System.out.println(file);

           


          •  


      • 对文件夹进行列出所有文件
        • list();
          • 文件.文件夹名称字符串数组
        • listFiles();
          • 文件.文件夹封装的 File 数组
      •        /*
                 * 如果目录不存在,不能列表
                 * 或者目录无权访问,也不能列表
                 */
                String[] fileNameArr = dir.list();
                File[] listFiles = dir.listFiles();
                
                System.out.println(Arrays.toString(fileNameArr));
                
                for (File file : listFiles) {
                    System.out.println(file.getName());
                }

         


    • 求目录中文件的总大小
    • public class Test5 {
          public static void main(String[] args) {
              File dir = new File("/Users/dingzhijie/Desktop/未命名文件夹");
              
              if (dir.isDirectory()) {
                  long size = dirLength(dir);
                  System.out.println(size);
              }
          }
      
          private static long dirLength(File dir) {
              
              /*
               * [a]
               *   | - b
               *   | - c
               *   | - [d]
               *   
               *   对dir 目录列表
               *   吧 列表文件和文件夹大小加一起
               */
              
              File[] listFiles = dir.listFiles();
              
              if (listFiles == null) {
                  return 0;
              }
              
              // 累加变量
              long sum = 0;
              
              for (File file : listFiles) {
                  if (file.isDirectory()) {
                      sum += dirLength(file);
                      // 文件夹递归求子文件夹大小
                  }else {
                      sum += file.length();
                      // 文件直接累加
                  }
              }
              
              return sum;
              
          }
      }

       

 

 

  •  RandomAccessFile
    • control+h  切换文本和数字
    •  有一个下标, 读写下标位置的字节值
    • 每读写一个字节值, 下标会自动向后移动
    • 下标可以任意定位
    • 创建对象
      • new RandomAccessFile(文件,"r"); // 只读
      • new RandomAccessFile(文件,"rw"); // 读写
    • 方法
      • write(int b);
        • int 的 四个字节, 只输出末尾的一个
        • 所以只输入 255 范围内的值
      • write(byte[]);
        • 输出数组中,全部字节值
      • write(byte[], start, length);
        • 输出数组中, 从 start 位置开始的 length 个字节值
    • package day1204;
      
      import java.io.IOException;
      import java.io.RandomAccessFile;
      
      public class Test1 {
          public static void main(String[] args) throws IOException {
      
              /*
               * 如果文件不存在, 自动新建文件
               * 如果文件夹不存在, 会报异常
               */
              RandomAccessFile raf = 
               new RandomAccessFile("/Users/dingzhijie/Desktop/UE_file1", "rw");
              
              raf.write(97);
              raf.write(98);
              raf.write(99);
              raf.write(356);
              
              //
              byte[] a = {101,102,103,104,105,106,107,108,110};
              raf.write(a);
              
              //
              raf.write(a, 2, 4);
              
              // 释放系统资源
              raf.close();
              
          }
      }

       

      • read();
        • 读取一个字节,再补三个 0 字节,变成 int 类型
        • 读取结束,无数据再读取返回 -1
      • seek(int position);
        • 定位下标到指定的位置
      • // 下标定位到 0  位置
        raf.seek(0);
                
        // 单字节读取
        int b; // 保存读取的字节值
                
        while ((b = raf.read()) != -1) {
            System.out.println(b);
        }

         


      • read(byte[]  buff);
        • 根据数组长度读取一批字节值,并返回这一批数据的数量
        • 因为数据数量可能不够数组长度
        • 读取结束,无数据再读取返回 -1
      •                // 批量读取
                raf.seek(0);// 定位下标到 0
                
                byte[] buff = new byte[4];
                
                int c;
                while ((c = raf.read(buff)) != -1) {
                    System.out.println(c+"\t"+Arrays.toString(buff));
                }
      •   getFilePointer();                 
        • 当前下标所在的位置

 

    • 文件的加密 . 解密
      • 用一个值, 对每个字节值求异或
    • package day1301;
      
      import java.io.File;
      import java.io.RandomAccessFile;
      import java.util.Scanner;
      
      public class Test1 {
          public static void main(String[] args) {
      
              System.out.println("输入文件:");
              Scanner scanner = new Scanner(System.in);
              String s = scanner.nextLine();
      
              File file = new File(s);
              
              if (!file.isFile()) {
                  System.out.println("不是文件");
                  return;
              }
              
              System.out.println("加密key:");
              
              
              int key = scanner.nextInt();
              
              try {
                  encrypt(file,key);
                  System.out.println("加密/解密成功");
              } catch (Exception e) {
                  System.out.println("失败");
                  e.printStackTrace();
              }
              
          }
      
          private static void encrypt(File file, int key) throws Exception {
              /*
               * 从文件读取一个字节值
               * 对 key 异或后,再写回到文件
               */
              
              RandomAccessFile raf = 
                      new RandomAccessFile(file, "rw");
              
              // 单字节读写
      //        int b;
      //        while ((b = raf.read()) != -1) {
      //            b ^= key; // 异或加密, 解密
      //            // 下标往前挪一位
      //            raf.seek(raf.getFilePointer()-1);
      //            // 字节值写回到文件
      //            raf.write(b);
      //        }
              
              // 批量读写
              byte[] buff = new byte[8192]; // 一般用 8192 , 8k
              int n;
              while ((n = raf.read(buff)) != -1) {
                  for (int i = 0; i < n; i++) {
                      buff[i] ^= key;
                  }
                  
                  // 下标前移 n 个位置
                  raf.seek(raf.getFilePointer()-n);
                  // 写回文件, 从 0 位置开始的 前 n 个写回文件
                  raf.write(buff, 0, n);;
              }
              
              // 批量读写速度更快, 推荐
              
              raf.close();
              
          }
      }
posted @ 2019-07-11 08:45  Dingzhijie  阅读(243)  评论(0编辑  收藏  举报