可以读写基本数据类型的数据 数据输入流:DataInputStream DataInputStream(InputStream in) 数据输出流:DataOutputStream DataOutputStream(OutputStream out) ===================================public static void main(String[] args) throws IOException { // 写 // write(); // 读 read(); } private static void read() throws IOException { // DataInputStream(InputStream in) // 创建数据输入流对象 DataInputStream dis = new DataInputStream( new FileInputStream("dos.txt")); // 读数据 byte b = dis.readByte(); short s = dis.readShort(); int i = dis.readInt(); long l = dis.readLong(); float f = dis.readFloat(); double d = dis.readDouble(); char c = dis.readChar(); boolean bb = dis.readBoolean(); // 释放资源 dis.close(); System.out.println(b); System.out.println(s); System.out.println(i); System.out.println(l); System.out.println(f); System.out.println(d); System.out.println(c); System.out.println(bb); } private static void write() throws IOException { // DataOutputStream(OutputStream out) // 创建数据输出流对象 DataOutputStream dos = new DataOutputStream(new FileOutputStream( "dos.txt")); // 写数据了 dos.writeByte(10); dos.writeShort(100); dos.writeInt(1000); dos.writeLong(10000); dos.writeFloat(12.34F);//有一个类型转换 dos.writeDouble(12.56); dos.writeChar('a'); dos.writeBoolean(true); // 释放资源 dos.close(); }==========================================注意一个问题,如果只有DataOutputStream来写文件,直接双击打开文件,读到的数据是乱码 3.内存操作流的概述和讲解内存操作流:用于处理临时存储信息的,程序结束,数据就从内存中消失。 字节数组: ByteArrayInputStream ByteArrayOutputStream 字符数组: CharArrayReader CharArrayWriter 字符串: StringReader StringWriter
对于ByteArrayOutputStream:
此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用toByteArray()
和 toString()
获取数据。
关闭 ByteArrayOutputStream
无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException
。(说白了就是不用close方法了)
对于ByteArrayInputStream
:
ByteArrayInputStream
包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪 read
方法要提供的下一个字节。
关闭 ByteArrayInputStream
无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException
。
public static void main(String[] args) throws IOException { // 写数据 // ByteArrayOutputStream() ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 写数据 for (int x = 0; x < 10; x++) { baos.write(("hello" + x).getBytes()); } // 释放资源 // 通过查看源码我们知道这里什么都没做,所以根本需要close() // baos.close(); // public byte[] toByteArray() byte[] bys = baos.toByteArray(); // 读数据 // ByteArrayInputStream(byte[] buf) ByteArrayInputStream bais = new ByteArrayInputStream(bys); int by = 0; while ((by = bais.read()) != -1) { System.out.print((char) by); } // bais.close();//不需要close } 4.打印流的概述和特点 打印流 字节流打印流 PrintStream 字符打印流 PrintWriter 打印流的特点: A:只有写数据的,没有读取数据。只能操作目的地,不能操作数据源。 B:可以操作任意类型的数据。 C:如果启动了自动刷新,能够自动刷新。(如果不启动的话,不刷新文件(就是flush或者close)里面是没有数据的) D:该流是可以直接操作文本文件的。 哪些流对象是可以直接操作文本文件的呢? FileInputStream FileOutputStream FileReader FileWriter PrintStream PrintWriter 看API,查流对象的构造方法,如果同时有File类型和String类型的参数,一般来说就是可以直接操作文件的。 流: 基本流:就是能够直接读写文件的 高级流:在基本流基础上提供了一些其他的功能 ==========================================public static void main(String[] args) throws IOException { // 作为Writer的子类使用 PrintWriter pw = new PrintWriter("pw.txt"); pw.write("hello"); pw.write("world"); pw.write("java"); pw.close();//没有这句话不出数据,因为这不是自动刷新的(或者) } 5.PrintWriter实现自动刷新和换行 可以操作任意类型的数据。 print() println() public static void main(String[] args) throws IOException { PrintWriter pw = new PrintWriter("pw2.txt"); pw.print("hello");//print方法可接受任意类型的数据 pw.print(100); pw.print(true); pw.close(); } 但以上的方法并没有实现自动刷新要实现自动刷新的话, 启动自动刷新 PrintWriter pw = new PrintWriter(new FileWriter("pw2.txt"), true);//要设置true 还是应该调用println()的方法才可以(调用print自动刷新不了) 这个时候不仅仅自动刷新了,还实现了数据的换行。public static void main(String[] args) throws IOException { // 创建打印流对象 // PrintWriter pw = new PrintWriter("pw2.txt"); PrintWriter pw = new PrintWriter(new FileWriter("pw2.txt"), true); // write()是搞不定的,怎么办呢? // 我们就应该看看它的新方法 // pw.print(true); // pw.print(100); // pw.print("hello"); pw.println("hello"); pw.println(true); pw.println(100); pw.close(); } 注意:println() 其实等价于于: bw.write(); bw.newLine(); bw.flush(); 一句顶三句 6.打印流改进复制文本文件案例 需求:DataStreamDemo.java复制到Copy.java中 数据源: DataStreamDemo.java -- 读取数据 -- FileReader -- BufferedReader 目的地: Copy.java -- 写出数据 -- FileWriter -- BufferedWriter -- PrintWriter public static void main(String[] args) throws IOException { //以前的版本 // 封装数据源 BufferedReader br = new BufferedReader(new FileReader( "DataStreamDemo.java")); //封装目的地 BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java")); String line = null; while ((line = br.readLine()) != null) { bw.write(line); bw.newLine(); bw.flush(); } bw.close(); br.close(); }===============================================public static void main(String[] args) {// 打印流的改进版 // 封装数据源 BufferedReader br = new BufferedReader(new FileReader( "DataStreamDemo.java")); // 封装目的地 PrintWriter pw = new PrintWriter(new FileWriter("Copy.java"), true); String line = null; while((line=br.readLine())!=null){ pw.println(line); } pw.close(); br.close();}=============================================7.标准输入输出流概述和输出语句的本质------System.out 标准输入输出流 System类中的两个成员变量: public static final InputStream in “标准”输入流。 public static final PrintStream out “标准”输出流。 InputStream is = System.in; PrintStream ps = System.out;public static void main(String[] args) { // 有这里的讲解我们就知道了,这个输出语句其本质是IO流操作,把数据输出到控制台。 System.out.println("helloworld"); // 获取标准输出流对象 PrintStream ps = System.out; ps.println("helloworld"); ps.println(); // ps.print();//这个方法不存在 // System.out.println(); // System.out.print(); } 8.标准输入输出流概述和输出语句的本质------System.in public static void main(String[] args) throws IOException { //获取标准输入流 InputStream is = System.in; //我要一次获取一行行不行呢? //行。 //怎么实现呢? //要想实现,首先你得知道一次读取一行数据的方法是哪个呢? //readLine() //而这个方法在哪个类中呢? //BufferedReader //所以,你这次应该创建BufferedReader的对象,但是底层还是的使用标准输入流 // BufferedReader br = new BufferedReader(is); //按照我们的推想,现在应该可以了,但是却报错了 //原因是:字符缓冲流只能针对字符流操作,而你现在是字节流,所以不能是用? //那么,我还就想使用了,请大家给我一个解决方案? //把字节流转换为字符流,然后在通过字符缓冲流操作 // InputStreamReader isr = new InputStreamReader(is); // BufferedReader br= new BufferedReader(isr); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); //注意这里的字节流转换成字符流,利用了InputStreamReader转换流 System.out.println("请输入一个字符串:"); String line = br.readLine(); System.out.println("你输入的字符串是:" + line); System.out.println("请输入一个整数:"); // int i = Integer.parseInt(br.readLine()); line = br.readLine(); int i = Integer.parseInt(line); System.out.println("你输入的整数是:" + i); } //利用上述代码模仿了Scanner的键盘录入功能注意以下方法 9.输出语句用字符缓冲流改进public static void main(String[] args) throws IOException { // 获取标准输入流 // // PrintStream ps = System.out; // // OutputStream os = ps;//这个就是多态 //上面两句简化为一句---- OutputStream os = System.out; // 多态 // // 我能不能按照刚才使用标准输入流的方式一样把数据输出到控制台呢? // OutputStreamWriter osw = new OutputStreamWriter(os); // BufferedWriter bw = new BufferedWriter(osw); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( System.out));//合并为一句 bw.write("hello"); bw.newLine(); // bw.flush(); bw.write("world"); bw.newLine(); // bw.flush(); bw.write("java"); bw.newLine(); bw.flush(); bw.close(); } 10.随机访问流概述和写出数据随机访问流: RandomAccessFile类不属于流,是Object类的子类。 但它融合了InputStream和OutputStream的功能。 支持对文件的随机访问读取和写入。 public RandomAccessFile(String name,String mode):第一个参数是文件路径,第二个参数是操作文件的模式。 模式有四种,我们最常用的一种叫"rw",这种方式表示我既可以写数据,也可以读取数据 这个RandomAccessFile类还可以读和写 11.随机访问流读取数据和操作文件指针===========================================public static void main(String[] args) throws IOException { read(); } private static void read() throws IOException { // 创建随机访问流对象 RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw"); int i = raf.readInt(); System.out.println(i); // 该文件指针可以通过 getFilePointer方法读取,并通过 seek 方法设置。 System.out.println("当前文件的指针位置是:" + raf.getFilePointer());//4 char ch = raf.readChar(); System.out.println(ch); System.out.println("当前文件的指针位置是:" + raf.getFilePointer());//6 String s = raf.readUTF(); System.out.println(s); System.out.println("当前文件的指针位置是:" + raf.getFilePointer());//14(本来是12的,多出来两个字节的原因可以看API,其实是识别UTF编码的两个字节) // 我不想重头开始了,我就要读取a,怎么办呢? raf.seek(4);//从0开始计算 ch = raf.readChar(); System.out.println(ch); }======================================================输出示例12.合并流读取两个文件的内容复制到一个文件中合并流就是按顺序读取两个文件然后合并到一个新的文件中public static void main(String[] args) throws IOException { InputStream is1 = new FileInputStream("pw.txt"); InputStream is2 = new FileInputStream("pw2.txt"); // SequenceInputStream(InputStream s1, InputStream s2) SequenceInputStream sis = new SequenceInputStream(is1, is2); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.txt")); // 如何写读写呢,其实很简单,你就按照以前怎么读写,现在还是怎么读写 byte[] bys = new byte[1024]; int len = 0; while ((len = sis.read(bys)) != -1) { bos.write(bys, 0, len); } sis.close(); bos.close();=============================================运行示例运行前 运行后 13.合并流读取多个文件的内容复制到一个文件中public static void main(String[] args) throws IOException {
// 需求:把下面的三个文件的内容复制到pwsum.txt中 // SequenceInputStream(Enumeration e) // 通过简单的回顾我们知道了Enumeration是Vector中的一个方法的返回值类型。 // Enumeration<E> elements() Vector<InputStream> v = new Vector<InputStream>(); InputStream is1 = new FileInputStream("pw.txt"); InputStream is2 = new FileInputStream("pw2.txt"); InputStream is3 = new FileInputStream("pw3.txt"); v.add(is1); v.add(is2); v.add(is3); Enumeration<InputStream> e = v.elements(); SequenceInputStream sis = new SequenceInputStream(e);//接收一个参数 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("pwsum.txt")); byte[] bys = new byte[1024]; int len = 0; while ((len = sis.read(bys)) != -1) { bos.write(bys, 0, len); } sis.close(); bos.close(); } 14.序列化流和反序列化流的概述和使用序列化流 ObjectOutputStream反序列化流 ObjectInputStream 序列化流:把对象按照流一样的方式存入文本文件或者在网络中传输。对象 -- 流数据(ObjectOutputStream) 反序列化流:把文本文件中的流对象数据或者网络中的流对象数据还原成对象。流数据 -- 对象(ObjectInputStream) 首先,写序列化流Demo的write方法。public static void main(String[] args) throws IOException, ClassNotFoundException { // 由于我们要对对象进行序列化,所以我们先自定义一个类 // 序列化数据其实就是把对象写到文本文件 write(); } private static void write() throws IOException { // 创建序列化流对象 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream( "oos.txt")); // 创建对象 Person p = new Person("林青霞", 27); // public final void writeObject(Object obj) oos.writeObject(p); // 释放资源 oos.close(); }======================================================然后,创建一个Person类import java.io.Serializable; public class Person implements Serializable { private String name; private int age; public Person() { super(); } public Person(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } }============================要说明的是,在Person类还没实现 Serializable 这个接口的时候,运行会有异常NotSerializableException:未序列化异常查API 因此,要想没报错,必须在Person类中实现 Serializable 这个接口但是:你会发现,没有重写任何方法啊!!!没错,因为,本来就不用重写任何的方法!解析如下:类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。 该接口居然没有任何方法,类似于这种没有方法的接口被称为标记接口。然后,再次运行没报错后,直接打开文件是看不懂的 序列化的流必须要反序列的流"解锁"才可以啊最后,加入反序列流的代码如下 运行(不报错了)toString方法在Person类中已经重写注意这一步 // 还原对象 Object obj = ois.readObject();obj虽然是Object类型,但是其实是Person对象 但是,还有一个小问题如何解决序列化时候的黄色警告线问题 当Person类进行了改动的时候(比如private int age 改为 int age)把代码保存再次运行(只执行读操作而不进行第二次写入)会报错产生异常 产生的原因: 为什么会有问题呢? Person类实现了序列化接口,那么它本身也应该有一个标记值。 这个标记值假设是100。 开始的时候: Person.class -- id=100 wirte数据: oos.txt -- id=100 read数据: oos.txt -- id=100 现在: Person.class -- id=200 wirte数据: oos.txt -- id=100 read数据: oos.txt -- id=100解决这个问题的办法:我们在实际开发中,可能还需要使用以前写过的数据,不能重新写入。怎么办呢? 回想一下原因是因为它们的id值不匹配。 每次修改java文件的内容的时候,class文件的id值都会发生改变。 而读取文件的时候,会和class文件中的id值进行匹配。所以,就会出问题。 但是呢,如果我有办法,让这个id值在java文件中是一个固定的值,这样,你修改文件的时候,这个id值还会发生改变吗? 不会。现在的关键是我如何能够知道这个id值如何表示的呢? 不用担心,你不用记住,也没关系,点击鼠标即可。 你难道没有看到黄色警告线吗? 在Person类中加一下语句private static final long serialVersionUID = -2071565876962058344L; 还有一个要注意的问题:注意: 我一个类中可能有很多的成员变量,有些我不想进行序列化。请问该怎么办呢? 使用transient关键字声明不需要序列化的成员变量也就是用transient关键字 把private int age修改为private transient int age;然后运行会发现age的值为0了,也就是说,age的值将不被记住是27了 15.Properties的概述和作为Map集合的使用(注意:Properties并没有泛型) Properties:属性集合类。是一个可以和IO流相结合使用的集合类。 Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。 是Hashtable的子类,说明是一个Map集合。 public static void main(String[] args) { // 作为Map集合的使用 // 下面这种用法是错误的,一定要看API,如果没有<>,就说明该类不是一个泛型类,在使用的时候就不能加泛型 // Properties<String, String> prop = new Properties<String, String>(); Properties prop = new Properties(); // 添加元素 prop.put("it002", "hello"); prop.put("it001", "world"); prop.put("it003", "java"); // System.out.println("prop:" + prop); // 遍历集合,注意红字是Object而不是String,因为上面的put方法本来就是接受Object参数 Set<Object> set = prop.keySet(); for (Object key : set) { Object value = prop.get(key); System.out.println(key + "---" + value); } } 16.Properties的特殊功能使用特殊功能: public Object setProperty(String key,String value):添加元素 public String getProperty(String key):获取元素 public Set<String> stringPropertyNames():获取所有的键的集合=========================public static void main(String[] args) { // 创建集合对象 Properties prop = new Properties(); // 添加元素 prop.setProperty("张三", "30"); prop.setProperty("李四", "40"); prop.setProperty("王五", "50"); // public Set<String> stringPropertyNames():获取所有的键的集合 Set<String> set = prop.stringPropertyNames(); for (String key : set) { String value = prop.getProperty(key); System.out.println(key + "---" + value); } }================================================17.Properties的load()和store()功能这里的集合必须是Properties集合: public void load(Reader reader):把文件中的数据读取到集合中 public void store(Writer writer,String comments):把集合中的数据存储到文件================================================= public static void main(String[] args) throws IOException { myLoad(); myStore(); } private static void myStore() throws IOException { // 创建集合对象 Properties prop = new Properties(); prop.setProperty("林青霞", "27"); prop.setProperty("武鑫", "30"); prop.setProperty("刘晓曲", "18"); //public void store(Writer writer,String comments):把集合中的数据存储到文件 Writer w = new FileWriter("name.txt"); prop.store(w, "helloworld");//这个helloworld只是注释的作用。。。 w.close(); } private static void myLoad() throws IOException { Properties prop = new Properties(); // public void load(Reader reader):把文件中的数据读取到集合中 // 注意:这个文件的数据必须是键值对形式 Reader r = new FileReader("prop.txt"); prop.load(r); r.close(); System.out.println("prop:" + prop); } 运行打开name.txt文件 18.判断文件中是否有指定的键如果有就修改值的案例 我有一个文本文件(user.txt),我知道数据是键值对形式的,但是不知道内容是什么。 请写一个程序判断是否有“lisi”这样的键存在,如果有就改变其实为”100” 分析: A:把文件中的数据加载到集合中 B:遍历集合,获取得到每一个键 C:判断键是否有为"lisi"的,如果有就修改其值为"100" D:把集合中的数据重新存储到文件中========================================public static void main(String[] args) throws IOException { // 把文件中的数据加载到集合中 Properties prop = new Properties(); Reader r = new FileReader("user.txt"); prop.load(r); r.close(); // 遍历集合,获取得到每一个键 Set<String> set = prop.stringPropertyNames(); for (String key : set) { // 判断键是否有为"lisi"的,如果有就修改其值为"100" if ("lisi".equals(key)) { prop.setProperty(key, "100"); break; } } // 把集合中的数据重新存储到文件中 Writer w = new FileWriter("user.txt"); prop.store(w, null);//这里设为null,不用附加东西了 w.close(); }=============================================user.txt运行后 19.如何让猜数字小游戏只能玩5次案例 我有一个猜数字小游戏的程序,请写一个程序实现在测试类中只能用5次,超过5次提示:游戏试玩已结束,请付费。初始化:手动建一个文件保存玩游戏的次数(不需要写代码创建文件)public static void main(String[] args) throws IOException { // 读取某个地方的数据,如果次数不大于5,可以继续玩。否则就提示"游戏试玩已结束,请付费。 // 把数据加载到集合中 Properties prop = new Properties(); Reader r = new FileReader("count.txt"); prop.load(r); r.close();//别忘记关闭流 // 我自己的程序,我当然知道里面的键是谁 String value = prop.getProperty("count"); int number = Integer.parseInt(value);//String转换为int if (number > 5) { System.out.println("游戏试玩已结束,请付费。"); System.exit(0);//别漏了这一步退出!! } else { number++; prop.setProperty("count", String.valueOf(number));//int转为String Writer w = new FileWriter("count.txt"); prop.store(w, null); w.close();//别忘记关闭流 GuessNumber.start();//这个猜数字的小游戏代码省略 } } 注意几个问题:别忘记关闭流,注意字符串与Integer的转换.别漏了 System.exit(0)==================================================20.NIO的介绍和JDK7下NIO的一个案例NIO:就是New IOnio包在JDK4出现,提供了IO流的操作效率。但是目前还不是大范围的使用。 有空的话了解下,有问题再问我。 JDK7的之后的nio: Path:路径 Paths:有一个静态方法返回一个路径 public static Path get(URI uri)//返回值为Path Files:提供了静态方法供我们使用 public static long copy(Path source,OutputStream out):复制文件 public static Path write(Path path,Iterable<? extends CharSequence> lines,Charset cs,OpenOption... options)//后面那个可变参数就忽略不理,只接受3个参数===================================================以下为课后阅读资料
1:JDK4新IO要了解的类(自己看)
Buffer(缓冲),Channer(通道)
2:JDK7要了解的新IO类
Path:与平台无关的路径。
Paths:包含了返回Path的静态方法。
public static Path get(URI uri):根据给定的URI来确定文件路径。
Files:操作文件的工具类。提供了大量的方法,简单了解如下方法
public static long copy(Path source, OutputStream out) :复制文件
public static Path write(Path path, Iterable<? extends CharSequence> lines, Charset cs, OpenOption... options):
把集合的数据写到文件。
//复制文件
Files.copy(Paths.get("Demo.java"), newFileOutputStream("Copy.Java"));
//把集合中的数据写到文件
List<String> list = new ArrayList<String>();
list.add("hello");
list.add("world");
list.add("java");
Files.write(Paths.get("list.txt"), list, Charset.forName("gbk"));
=================================================================================================
注意:ArrayList实现了Iterable接口
因此Iterable<? extends CharSequence> lines对应的参数可以是ArrayList的对象
先测试copy功能
然后测试write功能public static void main(String[] args) throws IOException { ArrayList<String> array = new ArrayList<String>(); array.add("hello"); array.add("world"); array.add("java"); Files.write(Paths.get("array.txt"), array, Charset.forName("GBK")); } ====================================================以下是自己写的代码Charset.forName("GBK")是设置编码的===========源运行后 运行后 ===================================================day22 笔记补充登录注册IO版本案例(掌握) 要求,对着写一遍。 写的顺序参考: cn.itcast.pojo User cn.itcast.dao UserDao cn.itcast.dao.impl UserDaoImpl(实现可以是集合版或者IO版) cn.itcast.game GuessNumber cn.itcast.test UserTest===============================================内存操作流(理解) (1)有些时候我们操作完毕后,未必需要产生一个文件,就可以使用内存操作流。 (2)三种 A:ByteArrayInputStream,ByteArrayOutputStream B:CharArrayReader,CharArrayWriter C:StringReader,StringWriter===============================================打印流(掌握) (1)字节打印流,字符打印流 (2)特点: A:只操作目的地,不操作数据源 B:可以操作任意类型的数据 C:如果启用了自动刷新,在调用println()方法的时候,能够换行并刷新 D:可以直接操作文件 问题:哪些流可以直接操作文件呢? 看API,如果其构造方法能够同时接收File和String类型的参数,一般都是可以直接操作文件的 (3)复制文本文件 BufferedReader br = new BufferedReader(new FileReader("a.txt")); PrintWriter pw = new PrintWriter(new FileWriter("b.txt"),true); String line = null; while((line=br.readLine())!=null) { pw.println(line); } pw.close(); br.close();=============================================== 5:标准输入输出流(理解) (1)System类下面有这样的两个字段 in 标准输入流 out 标准输出流 (2)三种键盘录入方式 A:main方法的args接收参数 B:System.in通过BufferedReader进行包装 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); C:Scanner Scanner sc = new Scanner(System.in); (3)输出语句的原理和如何使用字符流输出数据 A:原理 System.out.println("helloworld"); PrintStream ps = System.out;//PrintStream 属于字节流 ps.println("helloworld"); B:把System.out用字符缓冲流包装一下使用 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));============================================================序列化流(理解) (1)可以把对象写入文本文件或者在网络中传输 (2)如何实现序列化呢? 让被序列化的对象所属类实现序列化接口。 该接口是一个标记接口。没有功能需要实现。 (3)注意问题: 把数据写到文件后,在去修改类会产生一个问题。 如何解决该问题呢? 在类文件中,给出一个固定的序列化id值。 而且,这样也可以解决黄色警告线问题 (4)面试题: 什么时候序列化? 如何实现序列化? 什么是反序列化?========================================================NIO(了解) (1)JDK4出现的NIO,对以前的IO操作进行了优化,提供了效率。但是大部分我们看到的还是以前的IO (2)JDK7的NIO的使用 Path:路径 Paths:通过静态方法返回一个路径 Files:提供了常见的功能 复制文本文件 把集合中的数据写到文本文件