06 IO流 05File的常用方法 + 序列化 + 反序列化 + transient + 序列化版本号 + IO和Properties联合使用
1、File的常用方法
/* * File的常用方法 * * * */ File f1 = new File("D:\\java_base\\day.txt"); //获取文件名 System.out.println("文件名: " + f1.getName()); //判断是否是个目录 System.out.println(f1.isDirectory()); //判断是否是个文件 System.out.println(f1.isFile()); //获取文件最后一次修改的时间 long haomiao = f1.lastModified(); //这个是毫秒 //将总毫秒换成日期 Date time = new Date(haomiao); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); String strTime = sdf.format(time); System.out.println(strTime); // 获取文件大小
System.out.println(f1.length()); // 11816字节
// File[] listFile() //获取当前目录下的所有子文件 File f = new File("D:\\java_base\\src"); File[] files = f.listFiles(); //foreach for(File file:files){ System.out.println(file.getAbsolutePath()); }
2、序列化
/*1、 * 对象的序列化与反序列化 * 序列化:拆分对象 ObjectOutputStream serialize java对象存储到文件中,将java对象的状态保存下来的过程 * 反序列化:组装对象 ObjectInputStream DeSerialize 将硬盘上的数据重新恢复到内存中,恢复成java对象 * 2、 * java.io.NotSerializableException Student对象不支持序列化 参与 序列化和反序列化的对象,必须实现这个接口Serialiable * 3、 * 注意:通过源代码发现,Serializable接口只是一个标志接口: * public interface Serializasble{ * } * 这个接口当中什么代码都没有 * 那么它起到一个什么作用呢? * 起到标识的作用,标志的作用,Havana虚拟机看到这个类是实现了这个接口,可能会对这个类进行特殊待遇 * * 4、 * java虚拟机看到Serializable接口之后,会自动生成一个序列化版本号 * */ //创建java对象 User user = new User(111,"zhangsan"); //序列化 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user")); //序列化对象 oos.writeObject(user); //刷新 oos.flush(); //关闭 oos.close();
3、反序列化
/* * 一次序列化多个对象 * 可以,可以将对象放到集合当中,序列化对象 *提示: * 参与序列化的ArrayList集合以及集合中元素User 都需要实现序列化接口 * */ ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user")); //开始反序列化 读 Object obj = ois.readObject(); //反序列化回来就是一个用户对象,所以会调用学生对象的toString方法 System.out.println(obj); ois.close(); ListuserList = new ArrayList<>(); userList.add(new User(1,"zhangsan")); userList.add(new User(2,"lisi")); userList.add(new User(3,"tiantian")); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user")); //序列化一个集合,这个集合对象中放了其他对象 oos.writeObject(userList); oos.flush(); oos.close();
4、transient
// transient 表示游离的, 不参与序列化 private transient int no; //no不参与序列化
5、序列化版本号
/* * 序列化版本号有什么用? * java.io.InvalidClassException: * //过了很久,Student这个类源代码改动了 * //源代码改动之后,需要重新编译,编译之后生成了全新的字节码文件 * //摒弃class文件再次运行的时候,java虚拟机生成的序列化版本号也会发生相应的改变 * 序列哈版本号不一致,会报错 * java语言中是采用什么机制来去区分类的 * 第一:首先通过类名进行比对,如果类名不一样,肯定不是同一个类 * 第二:如果类名一样,再怎么进行类的区分?靠序列化版本号进行区分 * 自动化序列化版本号的缺陷? * 一是代码确定后,不能进行修改 * 只要修改,代码重新编译,就会生成全新的序列化版本号, * 这时java虚拟机会认为是一个全新的类 * */ private static final long serialVersionID = 1L; //java虚拟机识别一个类的时候先通过类名,类名一致再通过序列化版本号
6、IO和Properties联合使用
/* * IO + Properties联合使用 * 这是一个非常好的设计理念: * 以后经常改变的数据,可以单独写到一个文件中,使用程序动态读取 * 将来只要修改这个文件的内容,java程序代码不需要改变,不需要重新编译,服务器不需要重启,就可以拿到动态的信息 * * 类似以上机制的这种文件称为配置文件,并且当配置文件中的格式是: * key = value key1 = value java规范中有要求,属性配置文件以.properties结尾,但这不是必须的 * 这种以.properties结尾的文件在java中称为:属性配置文件 * 其中Properties是专门存放属性配置文件内容的一个类
在属性配置文件中# 是注释,属性配置文件中的key重复的话,value会自动覆盖,可以有空格,最好别加空格,中间可以用等号和冒号隔开,不建议用冒号 “key=value” * */
FileReader reader = new FileReader("userinfo.txt"); //新建map集合 Properties pro = new Properties(); // pro.load(reader); //通过key值获取value String username = pro.getProperty("username"); String password = pro.getProperty("password"); System.out.println("username: " + username); System.out.println("password: " + password);