Java中的IO流和反射

简介: 流是指一连串流动的字符,是以先进先出的方式发送信息的通道。程序和数据之间是通过流进行关联的。

一、定义

流是指一连串流动的字符,是以先进先出的方式发送信息的通道。程序和数据之间是通过流进行关联的。

二、分类

1、按流向分
输出流:OutputStream和Writer作为基类
输入流:InputStream和Reader作为基类
2、按处理数据的单元划分
字节流:nputStream/OutputStream作为基类
字符流:Reader/Writer作为基类

三、流之间的层级关系

上层为基类
1、输入
Reader
InputStreamReader(可设置字符编码)    Bufferendreader(带有缓冲区)
InputStream
FileInputStream objecInputStream(反序列化) DateInputStream(读二进制文件)
2、输出
Writer
OuputStreamWriterr(可设置字符编码)    BufferendWriterr(带有缓冲区)
InputStream
FileOutputStream objecOutputStream(序列化) DateIOutputStream(读二进制文件)

四、流的正确使用

1、File类操作文件

package demo1;
import java.io.File;
import java.io.IOException;
/*
 * 使用File类创建文件,并实现更删除、显示文件名和路径操作
 */
public class Test1 {
  public static void main(String[] args) throws IOException {
    File file = new File("D:\\test1.txt");
    if(!file.exists()) {
      file.createNewFile();//不存在创建
    }else {
      file.delete();//存在删除
    }
    System.out.println("该文件的绝对路径名为"+file.getAbsolutePath());
    System.out.println("该文件名为:"+file.getName());
  }
}

特别注意:创建File对象的时候可以放决相对路径也可以放决对路径
直接写test.txt代表的是在该项目底下的文件
而如果携程D:\test.txt的话是代表此文件 在D盘下的文件

File类常用方法:

方法

说明

boolean exisit()

判断文件是否存在

String getName()

获得文件名

boolean creatNewFile()

创建文件(创建前要判断文件是否存在 )

2、使用字节流FileInputStream读文本文件

package demo2;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/*
 * 字节流FileInputStream读取文件
 */
public class Test1 {
  public static void main(String[] args) throws Exception {
    File file =new File("demo2.txt");
    FileInputStream fis = new FileInputStream(file);
    byte[] b = new byte[fis.available()];
    int data=-1;
    while((data=fis.read(b))!=-1) {
    }
    String str = new String(b);//将字节数组变为字符串
    System.out.println(str);
    fis.close();
  }
}

FileInputStream 常用方法

方法

说明

inr read((byte[] b)

将数据缓存在字节数组中最后通过String的构造方法将字节数组转换成字符串输出

int read()

一个字节一个字节的读

3、使用字节流FileInputStream和FileOutputStream复制文本文件

package demo2;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
 * 复制文件
 */
public class Test2 {
  public static void main(String[] args) {
    FileInputStream fis =null;
    FileOutputStream fos=null;
    try {
      fis= new FileInputStream("D:\\demo1.txt");
      byte[] b = new byte[fis.available()];
      int date =-1;
      while((date=fis.read(b))!=-1){
      }
      fos = new FileOutputStream("E:\\Java\\java学习\\代码\\demo1.txt");
      fos.write(b);
    } catch (FileNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }finally{
      if(null!=fos){
        try {
          fos.close();
        } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
      if(null!=fis){
        try {
          fis.close();
        } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }
  }
}

4、使用DataInputStream和DataOutputStream读写二进制文件

package demo3;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
/*
 * 复制图片,二进制流的应用
 */
public class Test1 {
  public static void main(String[] args) throws Exception {
    DataInputStream dis = new DataInputStream(new FileInputStream("D:\\1.jpg"));
    DataOutputStream  dos =new DataOutputStream(new FileOutputStream("E:\\Java\\java学习\\代码\\t.jpg"));
    int date=-1;
    while((date=dis.read())!=-1){
      dos.write(date);
    }
    dos.close();
    dis.close();
  }
}

5、字符流FileReader & FileWriter

package demo4;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
/*
 * 字符流FileReader & FileWriter
 */
public class Test1 {
  public static void main(String[] args) throws Exception {
    FileReader fr = new FileReader("demo2.txt");
    //方式一、一个字符一个字符的读
//    int date=-1;
//    while((date=fr.read())!=-1) {
//      System.out.print((char)date);
//    }
    //方式二:字符数组读文件
    char[] c = new char[1024];
    int data =-1;
    while((data=fr.read(c))!=-1) {
    }
    System.out.println(c);
    //为读出的文本文件追加字符
    FileWriter fw = new FileWriter("demo2.txt",true);
    fw.write("我做主");
    //关闭流
    fw.close();
    fr.close();
  }
}

6、使用带有缓冲区的流输入输出,异常处理

package demo5;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
/*
 * 使用带有缓冲区的流输入输出,异常处理
 */
public class Test1 {
  public static void main(String[] args) {
    InputStream is = null;
    InputStreamReader isr = null;
    BufferedReader br = null;
    BufferedWriter bw = null;
    try {
      // 读取文件
      is = new FileInputStream("demo5.txt");
      isr = new InputStreamReader(is, "GBK");
      br = new BufferedReader(isr);
      String info = null;
      while ((info = br.readLine()) != null) {
        System.out.println(info);
      }
      // 写入新的文本
      bw = new BufferedWriter(new FileWriter("demo5.txt", true));//熟悉之后都可以采用这种方式进行简写
      bw.newLine();
      bw.write("今天也要元气满满哦!");
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {//注意如果不管流的话会导致很多东西出现bug,如果有bug先找是否正确的关闭流了
      if (null != bw) {
        try {
          bw.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
      if (null != br) {
        try {
          br.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
      if (null != isr) {
        try {
          isr.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
      if (null != is) {
        try {
          is.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }
}

注意指定字符编码,请确认是GBK还是UTF-8

五、一个重要综合性利用流的例子

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
public class IoDemo1 {
  public static void main(String[] args) {
    InputStream is = null;
    InputStreamReader isr = null;
    BufferedReader br = null;
    OutputStream os = null;
    OutputStreamWriter osw = null;
    BufferedWriter bw = null;
    try {
      // 读
      is = new FileInputStream("t1.txt");
      isr = new InputStreamReader(is, "GBK");
      br = new BufferedReader(isr);
      String info = br.readLine();
      System.out.println(info);
      // 写
      os = new FileOutputStream("t2.txt",true);
      osw = new OutputStreamWriter(os, "GBK");
      bw = new BufferedWriter(osw);
      bw.newLine();
      bw.write(info);
    } catch (FileNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } finally {
      try {
        bw.close();
        osw.close();
        os.close();
        br.close();
        isr.close();
        is.close();
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
  }
}

特别注意:一定要关闭流,有时候没关闭会出现很多的错误

六、序列化和反序列化

1、使用序列化保存对象信息(写出 objecOutputStream)

2、使用反序列化获取对象信息(写出 objecInputStream)
3、例子:

package Demo1;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
/*
 * 序列化和反序列化
 */
public class Test1 {
  public static void main(String[] args) throws Exception, IOException {
    ArrayList<Student> list = new ArrayList<Student>();
    Student stu1 =new Student("jck",12,"男");
    Student stu2 =new Student("lick",13,"男");
    Student stu3 =new Student("as",12,"女");
    list.add(stu1);
    list.add(stu2);
    list.add(stu3);
    //反序列化储存
    ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream("demo1.txt"));
    oos.writeObject(list);
    //反序列化
    ObjectInputStream ois =new ObjectInputStream(new FileInputStream("demo1.txt"));
    Object obj=ois.readObject();
    ArrayList<Student> stuList = (ArrayList<Student> )obj;
    for(int i =0;i<stuList.size();i++) {
      Student stu=stuList.get(i);
      System.out.println(stu);
    }
  }
}

七、反射

package Demo2;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test1 {
  public static void main(String[] args) {
    //先获取Student类对应的Class对象
    Class cla=Student.class;
    //获取所有构造方法
    Constructor[] cons=cla.getConstructors();
    //获取所有构造方法的个数
    System.out.println(cons.length);
    //获取所有构造方法名字
    for (int i = 0; i < cons.length; i++) {
      System.out.println(cons[i].getName());
    }
    //获取共有的属性(只能是public修饰的)
    Field[] fields=cla.getFields();
    for (int i = 0; i < fields.length; i++) {
      System.out.println(fields[i].getName());
    }
    //获取所有的属性
    Field[] fis=cla.getDeclaredFields();
    for (int i = 0;  i< fis.length; i++) {
      System.out.println(fis[i].getType());
    }
    //获取类的方法
    Method[] methods=cla.getMethods();
    for (int i = 0; i < methods.length; i++) {
      System.out.println(methods[i].getName());
    }
  }
}
package Demo2;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
 * 通过反射使用有参构造方法构造Student对象
 * @author Administrator
 *
 */
public class Test2 {
  public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    //获取Student对应的Class对象
    Class<Student> cla=Student.class;
    //获取Class对象中的构造方法
    Constructor<Student> cons=cla.getConstructor(String.class,int.class,String.class);
    //为构造方法传递参数
    Student stu=cons.newInstance("jack",100,"123456");
    System.out.println(stu);
  }
}
package Demo2;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/*
 * 通过反射使用有参构造方法构造Student对象
 */
public class Test3 {
  public static void main(String[] args) throws Exception, SecurityException {
    //获取Student的class对象
    Class cla = Student.class;
    //获取Class对象中的构造方法
    Constructor<Student> cons=cla.getConstructor();
    Student stu=cons.newInstance();
    //获得指定set方法为属性赋值
    Method setNameMethod=cla.getDeclaredMethod("setName", String.class);
    setNameMethod.invoke(stu, "jack");
    Method setAgeMethod=cla.getDeclaredMethod("setAge", int.class);
    setAgeMethod.invoke(stu, 18);
    Method setSexMethod=cla.getDeclaredMethod("setSex", String.class);
    setSexMethod.invoke(stu, "男");
    System.out.println(stu);
  }
}
package Demo2;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
/*
 *通过反射直接为私有属性赋值 
 */
public class Test4 {
  public static void main(String[] args) throws Exception, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    // 获取Student的class对象
    Class cla = Student.class;
    // 获取Class对象中的构造方法
    Constructor<Student> cons = cla.getConstructor();
    Student stu = cons.newInstance();
    //访问私有成员
    Field nameField=cla.getDeclaredField("name");
    //获取私有属性的操作权限
    nameField.setAccessible(true);
    nameField.set(stu, "张三");
    Field ageField=cla.getDeclaredField("age");
    //获取私有属性的操作权限
    ageField.setAccessible(true);
    ageField.set(stu, 30);
    Field sexField=cla.getDeclaredField("sex");
    //获取私有属性的操作权限
    sexField.setAccessible(true);
    sexField.set(stu, "男");
    System.out.println(stu);
  }
}

反射机制在java框架中会用到!
掌握流的类名,通过相关的构造方法去构造流!

目录
相关文章
|
6天前
|
Java 大数据
解析Java中的NIO与传统IO的区别与应用
解析Java中的NIO与传统IO的区别与应用
|
7天前
|
Java 程序员 测试技术
解析Java中的反射机制及其应用场景
解析Java中的反射机制及其应用场景
|
7天前
|
存储 安全 Java
【Java】已解决java.io.ObjectStreamException异常
【Java】已解决java.io.ObjectStreamException异常
8 1
|
10天前
|
开发框架 Java Android开发
Java中的类反射与动态代理详解
Java中的类反射与动态代理详解
|
11天前
|
缓存 Java 测试技术
Java中的反射机制及其应用场景
Java中的反射机制及其应用场景
|
12天前
|
Java
Java中的反射与动态代理机制详解
Java中的反射与动态代理机制详解
|
12天前
|
存储 安全 Java
Java中的反射机制及其应用场景详解
Java中的反射机制及其应用场景详解
|
14天前
|
安全 Java
JAVA反射:如何在运行时“创造”你的对象?
【7月更文挑战第1天】Java反射机制允许在运行时动态创建对象,常用于插件系统和框架开发。与`new`关键字相比,反射提供更大的灵活性,能根据条件决定对象类型,但牺牲了性能和代码可读性。示例展示了如何通过`Class.forName()`和`Constructor.newInstance()`创建对象,过程中需处理异常。反射还可访问私有成员,增加安全风险,故使用时需谨慎。
12 2
|
13天前
|
安全 Java 测试技术
Java中的反射与元编程技术探秘
Java中的反射与元编程技术探秘
|
6天前
|
Java API
Java注解与反射机制
Java注解与反射概述: - 注解用于元数据,包括元注解`@Target`, `@Retention`, `@Documented`, `@Inherited`。 - 自定义注解用于自定义行为标记,参考[链接]例化后通过`getClass()`获取类信息。 - 主要API涉及类的多种获取方式,如`对象.getClass()`, `类名.class`, `Class.forName()`和内置类型`TYPE`。 - 应用场景包括动态创建对象,获取泛型和注解信息以及分析运行时结构。