百知教育 - 孙帅 - 17_IO编程
10_对象序列化的细节
- 类实现了Serializable接口: 此类对象反序列化不会调用构造方法。
- 该类继承的父类实现了Serializable接口: 反序列化时,父类对象和此类对象都不会调用构造方法。
- 该类实现了Serializable接口而父类没有实现: 反序列化时,父类调用无参构造方法重建对象,而该类对象不会调用构造方法。
-
代码1(利用异常EOFException判断对象文件结尾,跳出死循环):
package day23; import java.io.*; public class TestObjectStreamRead{ public static void main(String[] args){ FileInputStream fis = null; ObjectInputStream ois = null; try{ fis = new FileInputStream("student.dat"); ois = new ObjectInputStream(fis); while(true){ Object o = ois.readObject(); System.out.println(o); } }catch(Exception e){ System.out.println("end of file"); }finally{ try{ ois.close(); }catch(IOException e){ e.printStackTrace(); } } } }
-
运行结果:
-
代码2:
package day23; import java.io.*; public class TestDeSerializable{ public static void main(String[] args){ FileOutputStream fos = null; ObjectOutputStream oos = null; try{ fos = new FileOutputStream("student.dat"); oos = new ObjectOutputStream(fos); B b = new B(); oos.writeObject(b); System.out.println("Write Over"); }catch(Exception e){ e.printStackTrace(); }finally{ try{ oos.close(); }catch(IOException e){ e.printStackTrace(); } } FileInputStream fis = null; ObjectInputStream ois = null; try{ fis = new FileInputStream("student.dat"); ois = new ObjectInputStream(fis); ois.readObject(); System.out.println("Read Over"); }catch(Exception e){ e.printStackTrace(); }finally{ try{ ois.close(); }catch(IOException e){ e.printStackTrace(); } } } } class A { public A(){ System.out.println("A()"); } } class B extends A implements Serializable{ public B(){ System.out.println("B()"); } }
-
运行结果:
11_自定义序列化
-反序列化 时先调用无参构造方法,再调用自定义序列化规则 重建对象。
-
代码:
package day23; import java.io.*; public class TestExternalizable{ public static void main(String[] args){ Student s1 = new Student("YKY" , 20); FileOutputStream fos = null; ObjectOutputStream oos = null; try{ fos = new FileOutputStream("student.dat"); oos = new ObjectOutputStream(fos); oos.writeObject(s1); System.out.println("Write Over"); oos.close(); }catch(Exception e){ e.printStackTrace(); } FileInputStream fis = null; ObjectInputStream ois = null; try{ fis = new FileInputStream("student.dat"); ois = new ObjectInputStream(fis); Object o1 = ois.readObject(); System.out.println(o1); System.out.println("Read Over"); ois.close(); }catch(Exception e){ e.printStackTrace(); } } } class Student implements Externalizable{ String name; int age; public Student(String name , int age){ this.name = name; this.age = age; } public Student(){} @Override public String toString(){ return "Student [name="+name+", age="+age+"]"; } @Override public void writeExternal(ObjectOutput out) throws IOException{ out.writeUTF(name); out.writeInt(age); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException{ name = in.readUTF(); age = in.readInt(); } }
-
运行结果:
12_对象的浅克隆与深克隆
-
代码:
package day23; import java.io.*; public class TestClone{ public static void main(String[] args){ Address addr = new Address(); Worker w = new Worker("YKY" , 20 , addr); try{ Object o = w.clone(); Worker w1 = (Worker)o; System.out.println(w == w1); System.out.println(w.addr == w1.addr); }catch(CloneNotSupportedException e){ e.printStackTrace(); } } } class Worker implements Serializable , Cloneable{ String name; int age; Address addr; public Worker(){} public Worker(String name , int age , Address addr){ this.name = name; this.age = age; this.addr = addr; } @Override public String toString(){ return "Worker [name="+name+", age="+age+", addr="+addr+"]"; } @Override public Object clone() throws CloneNotSupportedException{ ByteArrayOutputStream baos = null; ObjectOutputStream oos = null; byte[] bs = null; try{ baos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(baos); oos.writeObject(this); bs = baos.toByteArray(); }catch(IOException e){ e.printStackTrace(); }finally{ try{ oos.close(); }catch(IOException e){ e.printStackTrace(); } } ByteArrayInputStream bais = null; ObjectInputStream ois = null; Object o = null; try{ bais = new ByteArrayInputStream(bs); ois = new ObjectInputStream(bais); o = ois.readObject(); }catch(IOException e){ e.printStackTrace(); }finally{ try{ ois.close(); }catch(IOException e){ e.printStackTrace(); } return o; } } } class Address implements Serializable{ String addr; }
-
运行结果:
13_中文乱码问题
-
字符的编码:
字符的编码方式和解码方式不统一,可能造成乱码问题。 -
几种常见的编码方式:
- ASCII: 美国
- ISO-8859-1: 西欧
- GB2312: 早期简体中文
- GBK: 扩充版简体中文
- Big5: 繁体中文(台湾、澳门、香港)
-
代码:
package day23; import java.io.UnsupportedEncodingException; public class TestEncoding{ public static void main(String[] args){ String str = "中关村软件园百知教育"; try{ byte[] bs = str.getBytes("GBK"); //编码 String str1 = new String(bs, "Big5"); //解码 System.out.println(str); System.out.println(str1); }catch(UnsupportedEncodingException e){ e.printStackTrace(); } } }
-
运行结果:
14_UTF-8编码方式
-
Unicode
- 全球统一
- UTF-16
- UTF-8
-
所有语种向上兼容ASCII编码方式,因此英文不会出现乱码
-
代码:
package day23; import java.io.UnsupportedEncodingException; public class TestEncoding{ public static void main(String[] args){ String str = "到百知,学Java"; try{ byte[] bs = str.getBytes("GBK"); //编码 String str1 = new String(bs, "Big5"); //解码 System.out.println(str); System.out.println(str1); }catch(UnsupportedEncodingException e){ e.printStackTrace(); } } }
-
运行结果:
15_字符流
-
Reader/Writer
字符流 的父类,抽象类- FileReader/FileWriter: 文件字符流,节点流
- BufferedReader/BufferedWriter: 缓冲流,过滤流
- PrintWriter 缓冲流,过滤流
- InputStreamReader/OutputStreamWriter: 常叫 桥转换类,具有桥转换功能,即 将字节流转换为字符流 ,转换时可以指定编码方式
-
代码(!!!PrintWriter是缓冲流,要用flush方法将数据从缓冲区写入文件,才能正确读文件):
package day23; import java.io.*; public class TestReaderAndWriter{ public static void main(String[] args){ FileOutputStream fos = null; OutputStreamWriter fw = null; PrintWriter pw = null; FileInputStream fis = null; InputStreamReader fr = null; BufferedReader br = null; try{ fos = new FileOutputStream("b.txt"); fw = new OutputStreamWriter(fos , "GBK"); pw = new PrintWriter(fw); //pw = new PrintWriter("b.txt"); //等价于上面三行,一步到位 pw.println("闺中少妇不知愁"); pw.println("春日凝妆上翠楼"); pw.println("忽见陌头杨柳色"); pw.println("悔教夫婿觅封侯"); pw.flush(); //!!!把缓冲区里的数据写入文件 System.out.println("Write Over"); fis = new FileInputStream("b.txt"); fr = new InputStreamReader(fis , "GBK"); br = new BufferedReader(fr); System.out.println("Read Begin"); while(true){ String s = br.readLine(); //每次读一行,读到换行符结束 if(s == null) break; System.out.println(s); } }catch(Exception e){ e.printStackTrace(); }finally{ try{ //pw.close(); br.close(); }catch(IOException e){ e.printStackTrace(); } } } }
-
运行结果:
16_File类
-
IO流:
对文件中的内容进行操作。 -
File类:
- 对文件自身进行操作,例如:删除文件,文件重新命名等。
- File 只代表 文件 或是 文件夹 ,不具有操作文件的功能所有的操作基于它提供的方法。
-
File类常用方法:
- public boolean createNewFile(): 创建文件,创建成功返回true,如果文件存在返回值为false。
- public boolean mkdir(): 创建文件夹,创建成功返回true,如果文件存在返回值为false。
- public boolean delete: 删除文件夹/文件,删除成功返回true,否则返回false。
- 当删除文件夹时,只有当文件夹为空时,才可以被删除。
- 而删除文件是,不管文件内容是否为空,都会被删除。
- public boolean renameTo(File f): 更改文件的名字,更改成功返回true,否则返回false。
- public boolean setReadOnly(): 设置文件为只读。
- public String getName(): 获取文件名(含扩展名)、文件夹名。
- public boolean exists(): 判断一个文件或是目录是否存在,存在返回true,否则返回false。
- public String getAbsolutePath(): 获得绝对路径。
- public File[] listFile(): 获取当前文件夹下所有的文件、文件夹。
- public boolean isFile(): 判断File对象所对应的是否为文件,而不是目录。
- public boolean isDirectory(): 判断File对象所对应的是否为目录,而不是文件。
-
代码:
package day23; import java.io.*; public class TestFile{ public static void main(String[] args){ /* File f = new File("abc"); try{ f.createNewFile(); }catch(IOException e){ e.printStackTrace(); } f.delete(); f.mkdir(); */ /* File dir = new File("C:\\Users\\念衷\\desktop\\java"); File[] fs = dir.listFiles(); for(File f : fs){ System.out.print(f.getName()+" "); if(f.isFile()) System.out.println("文件"); if(f.isDirectory()) System.out.println("目录"); } */ /* File dir = new File("abc"); deleteDir(dir); */ /* File dir = new File("C:\\Users\\念衷\\desktop\\java"); File[] fs = dir.listFiles(new FileFilter(){ public boolean accept(File pathname){ return pathname.isFile(); } }); for(File f : fs){ System.out.println(f.getName()); } */ File dir = new File("C:\\Users\\念衷\\desktop\\java"); listJavaFiles(dir); } static void deleteDir(File dir){ File[] fs = dir.listFiles(); for(File f : fs){ if(f.isFile()) f.delete(); if(f.isDirectory()) deleteDir(f); } dir.delete(); } static void listJavaFiles(File dir){ File[] fs = dir.listFiles(new FileFilter(){ public boolean accept(File pathname){ if(pathname.isFile()){ return pathname.getName().endsWith(".java"); } if(pathname.isDirectory()){ listJavaFiles(pathname); } return false; } }); for(File f : fs){ System.out.println(f.getName()); } } }
-
运行结果:
17_NIO_Buffer
-
ByteBuffer的两种创建方式:
- ByteBuffer.allocate(capacity);
- ByteBuffer.wrap(byte[] bs);
-
ByteBuffer中的方法:
- flip(): 使position = 0 , 一般用来从 写模式切换到读模式。
- clear(): 使position = 0 ,limit = 0 , 一般用来从 读模式切换到写模式。
-
ByteBuffer中的三个重要指针:
- position: 当前读写位置
- limit: 限制,即实际所存内容的capacity
- capacity: 容量
-
代码:
package day23; import java.io.*; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.channels.FileChannel; import java.nio.ByteBuffer; public class TestBuffer{ public static void main(String[] args){ //ByteBuffer buffer = ByteBuffer.allocate(20); /* FileOutputStream fos = null; FileChannel channel = null; ByteBuffer buffer = null; try{ fos = new FileOutputStream("a.txt"); channel = fos.getChannel(); buffer = ByteBuffer.wrap("HelloWorld".getBytes()); channel.write(buffer); }catch(IOException e){ e.printStackTrace(); }finally{ try{ channel.close(); }catch(IOException e){ e.printStackTrace(); } } */ FileInputStream fis = null; FileChannel channel = null; ByteBuffer buffer = null; try{ fis = new FileInputStream("a.txt"); channel = fis.getChannel(); buffer = ByteBuffer.allocate(10); /* System.out.println(channel.read(buffer)); byte[] bs = buffer.array(); for(byte b : bs){ System.out.print((char)b); } System.out.println(); */ while(true){ int len = channel.read(buffer); if(len == -1) break; buffer.flip(); while(buffer.hasRemaining()){ System.out.print((char)(buffer.get())); } System.out.println(); buffer.clear(); } }catch(IOException e){ e.printStackTrace(); }finally{ try{ channel.close(); }catch(IOException e){ e.printStackTrace(); } } ByteBuffer bb = ByteBuffer.wrap("百知教育".getBytes()); Charset cs = Charset.forName("GBK"); Charset bs2 = Charset.forName("Big5"); ByteBuffer bb2 = cs.encode("百知教育"); CharBuffer cb = cs.decode(bb2); System.out.println(cb); } }
-
运行结果:
18_利用NIO实现文件拷贝
-
代码:
package day23; import java.io.*; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.ByteBuffer; public class TestNIOFileCopy{ public static void main(String[] args){ long t1 = System.currentTimeMillis(); fileCopy2("04_用节点流实现文件拷贝.wmv" , "04_用节点流实现文件拷贝1.wmv"); long t2 = System.currentTimeMillis(); System.out.println("字节数组拷贝:"+(t2-t1)); long t3 = System.currentTimeMillis(); fileCopy3("04_用节点流实现文件拷贝.wmv" , "04_用节点流实现文件拷贝1.wmv"); long t4 = System.currentTimeMillis(); System.out.println("缓冲字节数组拷贝:"+(t4-t3)); long t5 = System.currentTimeMillis(); fileCopy4("04_用节点流实现文件拷贝.wmv" , "04_用节点流实现文件拷贝1.wmv"); long t6 = System.currentTimeMillis(); System.out.println("ByteBuffer拷贝:"+(t6-t5)); long t7 = System.currentTimeMillis(); fileCopy5("04_用节点流实现文件拷贝.wmv" , "04_用节点流实现文件拷贝1.wmv"); long t8 = System.currentTimeMillis(); System.out.println("MappedByteBuffer拷贝:"+(t8-t7)); long t9 = System.currentTimeMillis(); fileCopy5("04_用节点流实现文件拷贝.wmv" , "04_用节点流实现文件拷贝1.wmv"); long t10 = System.currentTimeMillis(); System.out.println("FileChannel的transferTo方法拷贝:"+(t10-t9)); } static void fileCopy2(String srcName , String destName){ InputStream in = null; OutputStream out = null; byte[] bs = new byte[1024]; try{ in = new FileInputStream(srcName); out = new FileOutputStream(destName); while(true){ int len = in.read(bs); if(len == -1) break; out.write(bs , 0 , len); } }catch(Exception e){ e.printStackTrace(); }finally{ try{ in.close(); out.close(); }catch(IOException e){ e.printStackTrace(); } } } static void fileCopy3(String srcName , String destName){ InputStream in = null; BufferedInputStream bis = null; OutputStream out = null; BufferedOutputStream bos = null; byte[] bs = new byte[1024]; try{ in = new FileInputStream(srcName); bis = new BufferedInputStream(in); out = new FileOutputStream(destName); bos = new BufferedOutputStream(out); while(true){ int len = bis.read(bs); if(len == -1) break; bos.write(bs , 0 , len); } }catch(Exception e){ e.printStackTrace(); }finally{ try{ bis.close(); bos.close(); }catch(IOException e){ e.printStackTrace(); } } } static void fileCopy4(String srcName , String destName){ FileInputStream fis = null; FileOutputStream fos = null; FileChannel fc1 = null; FileChannel fc2 = null; ByteBuffer buffer = ByteBuffer.allocate(1024); try{ fis = new FileInputStream(srcName); fos = new FileOutputStream(destName); fc1 = fis.getChannel(); fc2 = fos.getChannel(); while(true){ int len = fc1.read(buffer); if(len == -1) break; buffer.flip(); fc2.write(buffer); buffer.clear(); } }catch(IOException e){ e.printStackTrace(); }finally{ try{ fc1.close(); fc2.close(); }catch(IOException e){ e.printStackTrace(); } } } static void fileCopy5(String srcName , String destName){ FileInputStream fis = null; FileOutputStream fos = null; FileChannel fc1 = null; FileChannel fc2 = null; try{ fis = new FileInputStream(srcName); fos = new FileOutputStream(destName); fc1 = fis.getChannel(); fc2 = fos.getChannel(); MappedByteBuffer buffer = fc1.map(FileChannel.MapMode.READ_ONLY , 0 , fc1.size()); fc2.write(buffer); }catch(IOException e){ e.printStackTrace(); }finally{ try{ fc1.close(); fc2.close(); }catch(IOException e){ e.printStackTrace(); } } } static void fileCopy6(String srcName , String destName){ FileInputStream fis = null; FileOutputStream fos = null; FileChannel fc1 = null; FileChannel fc2 = null; try{ fis = new FileInputStream(srcName); fos = new FileOutputStream(destName); fc1 = fis.getChannel(); fc2 = fos.getChannel(); fc1.transferTo(0 , fc1.size() , fc2); }catch(IOException e){ e.printStackTrace(); }finally{ try{ fc1.close(); fc2.close(); }catch(IOException e){ e.printStackTrace(); } } } }
-
运行结果: