标签归档:IO流

注解、反射、文件IO流的综合应用

  • 准备一个简单的注解
    package com.yusian.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
    * 创建一个简单的注解SACheck
    * 该注解只能应用在方法上
    * 注解保留到运行时
    * 没有属性,只做标记用
    */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface SACheck {
    }
    
  • 准备一个简单的测试类
    package com.yusian.annotation;
    
    import org.junit.Assert;
    
    /**
    * 计算器类,几个简单的方法做演示
    */
    public class Calculator {
    
      @SACheck
      public void add() {
          int ret = add(1, 2);
          String str = null;
          str.toLowerCase();  // 人为制造bug,检测测试效果
          Assert.assertEquals(3, ret);
      }
    
      @SACheck
      public void sub() {
          int ret = sub(2, 1);
          ret = 1 / 0;    // 人为制造bug,检测测试效果
          Assert.assertEquals(1, ret);
      }
    
      @SACheck
      public void multiply() {
          int ret = multiply(2, 3);
          // 人为制造bug,检测测试效果
          Assert.assertEquals(5, ret);
      }
    
      public void show() {
          System.out.println("show...");
      }
    
      public int add(int a, int b) {
          return a + b;
      }
    
      public int sub(int a, int b) {
          return a - b;
      }
    
      public int multiply(int a, int b) {
          return a * b;
      }
    
      public int divide(int a, int b) {
          return a / b;
      }
    }
    
  • 通过反射机制及注解的标记测试带SACheck注解的方法,将测试结果写入本地文件
    package com.yusian.annotation;
    
    import java.io.*;
    import java.lang.reflect.Method;
    import java.util.Arrays;
    import java.util.concurrent.atomic.AtomicInteger;
    
    public class AnnoDemo {
      public static void main(String[] args) throws IOException{
          // 通过Calculator类对象获取所有的成员方法
          Calculator c = new Calculator();
          Method[] declaredMethods = c.getClass().getDeclaredMethods();
    
          // bug计数,这里本来可以定义一个int变量然后++就行了,但Lambda表达式中不支持修改外部变量
          AtomicInteger errNum = new AtomicInteger();
          // 准备一个IO写入流,检测出来的bug写入到文件中
          BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));
          // 使用流进行筛选与遍历,将带有@SACheck注解的方法执行并检测出是否异常,如果有则写入到文件
          Arrays.stream(declaredMethods).filter(method -> {
              return method.getAnnotation(SACheck.class) != null;
          }).forEach(method -> {
              try {
                  method.invoke(c);
              } catch (Exception e) {
                  try {
                      bw.write("错误类型:" + e.getCause().getClass().getSimpleName());
                      bw.newLine();
                      bw.write("错误原因:" + e.getCause().getMessage());
                      bw.newLine();
                      bw.write("-------------------");
                      bw.newLine();
                      errNum.getAndIncrement();
                  } catch (IOException ioException) {
                      ioException.printStackTrace();
                  }
              }
          });
          bw.write("共检测出" + errNum + "个bug");
          bw.newLine();
          bw.flush();
          bw.close();
      }
    }
    
  • 输出文件:bug.txt
    错误类型:NullPointerException
    错误原因:null
    -
    错误类型:AssertionError
    错误原因:expected:<5> but was:<6>
    -
    错误类型:ArithmeticException
    错误原因:/ by zero
    -
    共检测出3个bug
    

Java中IO流的相关操作

1 字节流

FileInputStreamFileOutputStream

        // IO流的读取与写入
        private static void demo01() throws IOException {
        // 如果是追加内容,则使用第二个参数为true的重载构造函数
        FileOutputStream fos = new FileOutputStream("1.txt");
        fos.write(97);
        fos.write(98);
        fos.write(99);
        fos.close();

        FileInputStream fis = new FileInputStream("1.txt");
        // 字节读取返回的是读取的字节十进制值,并且自动向后偏移,如果返回-1则表过读取完毕
        int data = fis.read();
        System.out.println((char) data);
        fis.close();

        // 一次读取多个字节
        FileInputStream fis2 = new FileInputStream("1.txt");
        int length = 0;
        byte[] bytes = new byte[1024];
        while((length = fis2.read(bytes)) != -1) {
            System.out.print(new String(bytes, 0, length));
        }
        fis2.close();
    }

2 字符流

FileReaderFileWrite

        // 字符流的读取与写入
    private static void demo02() throws IOException {
        // 如果是追加,则第二个参数传true
        FileWriter fw = new FileWriter("1.txt");
        fw.write(new char[]{'中', '国'});
        // 字符的写入是先保存在内存缓存区,需要调用flush方法才会真正的写入到文件
        fw.flush();

        // 单个字符读取
        FileReader fr = new FileReader("1.txt");
        // 文件的读取会以字符的单位一个一个读取,如果返回值为-1则表示读取完毕
        int c = fr.read();
        System.out.println((char) c);

        // 一次读取多个字符
        FileReader fr2 = new FileReader("1.txt");
        int length = 0;
        char[] charArray = new char[1024];
        while((length = fr2.read(charArray)) != -1) {
            System.out.print(new String(charArray, 0, length));
        }
        fr2.close();
    }

3 异常处理

关于换行符号
继续阅读