技术要点总结(2):IO流

IO流
  (1)概述:
    IO流用来处理设备之间的数据传输(上传和下载文件)问题
  (2)分类:(如果没有明确指定分类方式,默认指按照数据类型分)
  A:按照数据流向
    输入流 读入数据
    输出流 写出数据
  B:按照数据类型
    字节流
      a、字节输入流 读取数据 InputStream(此抽象类是表示字节输入流的所有类的超类)
      InputStream的实现类:FileInputStream类/BufferedInputStream类
      InputStream的成员方法:
      public abstract int read():从输入流中读取数据的下一个字节。如果因为已经到达流末尾而没有可用的字节,则返回值 -1 (实现类重写该抽象方法)
      public int read(byte[] b):从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组b 中。返回:读入缓冲区的总字节数;如果因为已经到达流末尾而不再有数据可用,则返回 -1。
      注意:数组的长达 b.length 一般取 1024 或者 1024 的整数倍
      b、字节输出流 写出数据 OutputStream(此抽象类是表示输出字节流的所有类的超类)
      OutputStream的实现类:FileOutputStream类/BuffereOutputStream类
      OutputStream的成员方法:
      public void write(byte[] b):将 b.length 个字节从指定的 byte 数组写入此输出流。
      public void write(byte[] b,int off,int len):将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
      public abstract void write(int b):将指定的字节写入此输出流(实现类重写此抽象方法)
      public void flush():刷新此输出流并强制写出所有缓冲的输出字节
      public void close():关闭此输出流并释放与此流有关的所有系统资源
    字符流(也称转换流由字节流和编码表组成;即根据编码表把字节流的数据转换为字符流)
      a、字符输入流 读取数据 Reader(用于读取字符流的抽象类)
      Reader的实现类:InputStreamReader类(子类-->FileReader类)/BufferedReader类
      Reader的成员方法:
        public int read():读取单个字符
        public int read(char[] cbuf):将字符读入数组。
      b、字符输出流 写出数据 Writer(用于写入字符流的抽象类)
      Writer的实现类:OutputStreamWriter类(子类-->FileWriter类)/BufferedWriter类
      Writer的成员方法:
        public void write(int c):写入单个字符
        public void write(char[] cbuf):写入字符数组
        public abstract void write(char[] cbuf,int off,int len):写入字符数组的某一部分。 off - 开始写入字符处的偏移量;len - 要写入的字符数
        public void write(String str):写入字符串
        public void write(String str,int off,int len):写入字符串的某一部分。 off - 相对初始写入字符的偏移量;len - 要写入的字符数
        public abstract void flush():刷新该流的缓冲
        public abstract void close():关闭此流,但要先刷新它。
        注意:字符流写数据要刷新缓冲区
  字节流和字符流的使用选择:
    如果文件能通过windows自带的记事本打开并能读懂里面的内容,那么建议使用字符流;否则建议使用字节流。(如果无法判断流对象,那么就使用字节流)
(3)FileOutputStream类
  A:构造方法
    public FileOutputStream(File file):创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
    public FileOutputStream(File file,boolean append):创建一个向指定 File 对象表示的文件中写入数据的文件输出流。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处
    public FileOutputStream(String name):创建一个向具有指定名称的文件中写入数据的输出文件流。
    public FileOutputStream(String name,boolean append):创建一个向具有指定 name 的文件中写入数据的输出文件流。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处
  B:成员方法
    public void write(int b):将指定字节写入此文件输出流。
  C:写出数据的操作步骤
    1)创建字节输出流对象( FileOutputStream fos = new FileOutputStream("fos.txt"); )
    2)调用write()方法写数据( fos.write("hello".getBytes()); )
    3)释放资源( fos.close(); )
  D:要注意的问题?
    1)创建字节输出流对象做了几件事情?
      A:调用系统功能去创建文件
      B:创建fos对象
      C:把fos对象指向这个文件
    2)为什么一定要close()?
      A:让流对象变成垃圾,以被垃圾回收器回收
      B:通知系统去释放跟该文件相关的资源
    3)如何实现数据的换行? -- fos.write("\r\n".getBytes());
     因为不同的系统针对不同的换行符号识别是不一样的:
     windows:\r\n       linux:\n  Mac:\r
     故应根据相应的操作系统写入相应的换行符(注意:一些常见的高级记事本,是可以识别任意换行符号的)
    4)如何实现数据的追加写入?
      用构造方法带第二个参数是true的情况即可
(4)FileInputStream类
  A:构造方法
    public FileInputStream(File file):通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
    public FileInputStream(String name):通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
  B:成员方法
    public int read():从此输入流中读取一个数据字节(返回:下一个数据字节;如果已到达文件末尾,则返回 -1)
  C:读取数据的操作步骤
    1)创建字节输入流对象( FileInputStream fis = new FileInputStream("fis.txt"); )
    2)调用read()方法读取数据,并把数据显示在控制台(
    //方式1 -- 一次读取一个字节
      int by = 0;
      // 读取,赋值,判断
      while((by=fis.read())!=-1) {
      //将字节转换为字符并输出
      System.out.print((char)by);
      }
    //方式2 -- 一次读取多个字节(每次可以读取多个数据,提高了操作效率)
      //创建字节数组(数组长度取1024或1024的整数倍)
      byte[] bys = new byte[1024];
      int len = 0;
      //当无字节可读时返回-1;
      while((len=fis.read(bys))!=-1) {
      //将字节数组转换为字符串并输出。
      System.out.print(new String(bys,0,len));
      注意:每次读取的数据将前一次读取得到的各数据依次替换,如果不带len使用,最后一次读取的结果将多出上一次读取结果中未替换掉的数据,所以这里千万要带上len的使用})
    3)释放资源( fis.close(); )
    注意:同一个流对象针对这两种读取方式在同一个代码中只能选择一个,因为流对象在一种方式读取完毕的时候已经读取到文件的末尾,那么另一种方式将无数据可读。
(5)字节缓冲区流(增加读写速度)
  A:字节缓冲输出流(写数据) -- BufferedOutputStream
    构造方法(可以指定缓冲区的大小,但是一般选默认缓冲区大小)
    public BufferedOutputStream(OutputStream out):创建一个新的缓冲输出流,以将(默认缓冲区大小)数据写入指定的底层输出流。
    public BufferedOutputStream(OutputStream out,int size):创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。
    例://创建字节输出缓冲区(传递的是输出流对象)
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("bos.txt"));
      // 写数据(写到指定的底层输出流) -- 存储在Box.txt中
      bos.write("hello".getBytes());
      // 释放资源
      bos.close();
  B:字节缓冲输入流(读数据) -- BufferedInputStream
    构造方法
      public BufferedInputStream(InputStream in):创建一个缓冲输入流并保存其参数(输入流对象in)。
      public BufferedInputStream(InputStream in,int size):创建具有指定缓冲区大小的缓冲输入流并保存其参数(输入流对象in)。
(6)转换流(转换流其实是一个字符流,即 字符流 = 字节流 + 编码表)
  A.概述:由于字节流操作中文不是特别方便,所以,java就提供了转换流。
  B.作用:转换流的作用就是把字节流转换字符流来使用。
  C.编码表:就是由字符和对应的数值组成的一张表
  常见编码表:
    ASCII:美国标准信息交换码;用一个字节的7位表示(-128~127)
    GBK:中国的中文编码表升级;
    Unicode:国际标准码;融合了多种文字。
  注:所有文字都用两个字节来表示,Java语言使用编码表是Unicode
    UTF-8:最多用三个字节来表示一个字符。
  D.字符串的编解码问题(编解码格式一致,才能得到原编码内容)
  1)对字符串进行编码(String --> byte[]) --> 采用不同的编码方式得到不同的字节数组。
   public byte[] getBytes(String charsetName): 使用指定的编码表将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。 charsetName--编码表名称
  2)对字节数组进行解码(byte[] -- String) --> 采用不同的解码方式得到不同的字符序列。
   public String(byte[] bytes,String charsetName):通过使用指定的编码表解码指定的 byte 数组,构造一个新的 String。
  E.IO流中的编解码问题
  OutputStreamWriter 字符输出流 写数据 (字符流=字节流+编码表)
    public OutputStreamWriter(OutputStream out):创建使用默认字符编码(GBK)的字符输出流(根据默认编码把字节输出流的数据转换为字符输出流)
    public OutputStreamWriter(OutputStream out,String charsetName):创建使用指定字符编码的字符
    输出流(根据指定编码把字节流数据转换为字符流) 参数:charsetName - 受支持的编码表名称
  InputStreamReader 字符输入流 读数据
    public InputStreamReader(InputStream in):创建一个使用默认字符集(GBK)的字符输入流
    public InputStreamReader(InputStream in,String charsetName):创建使用指定编码表的字符输入流

  字符流读取数据:
    InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"), "UTF-8");
    // 一次读取一个字符
    int ch = 0;
    while ((ch = isr.read()) != -1) {
    //注意这里用print以保证原文件格式
    System.out.print((char) ch);
    }
    /*// 一次读取一个字符数组
    char[] chs = new char[1024];
    int len = 0;
    while ((len = isr.read(chs)) != -1) {
    System.out.print(new String(chs, 0, len));
    }*/
    // 释放资源
    isr.close();
  字符流写出数据:(要刷新缓冲区)
    OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"), "UTF-8");
    // 写数据
    osw.write("中国");
    // 刷新缓冲区
    osw.flush();
    // 释放资源
    osw.close();
  !!!close()和flush()的区别?
    A:close():关闭流对象,但是先刷新一次缓冲区。关闭之后,流对象不可以继续再使用了。
    B:flush():仅仅刷新缓冲区,刷新之后,流对象还可以继续使用。
(7)字符流的便捷类
  由于我们常见的操作都是按照本地默认编码实现的,所以,我们一般使用InputStreamReader类的子类-->FileReader类和OutputStreamWriter类的子类-->FileWriter类来读写数据
  FileReader类的构造方法:(从给定文件中读取数据) -- 字符输入流的便捷类
    public FileReader(File file):通过给定File对象创建一个新字符输入流
    public FileReader(String fileName):通过给定文件名创建一个新字符输入流
  FileWriter类的构造方法:(向给定文件中写出数据) -- 字符输出流的便捷类
    public FileWriter(File file):根据给定的 File 对象构造一个字符输出流对象。
    public FileWriter(File file,boolean append):根据给定的 File 对象构造一个字符输出流对象。
      如果第二个参数为 true,则将字符写入文件末尾处,而不是写入文件开始处。
      public FileWriter(String fileName):根据给定的文件名构造一个字符输出流对象。
      public FileWriter(String fileName,boolean append):根据给定的文件名对象构造一个字符输出流对象。
      如果第二个参数为 true,则将字符写入文件末尾处,而不是写入文件开始处。
  例:通过字节流的便捷类复制数据
  /*数据源:
    a.txt -- 读取数据 -- 字符转换流 -- InputStreamReader -- FileReader
  目的地:
    b.txt -- 写出数据 -- 字符转换流 -- OutputStreamWriter -- FileWriter*/

 1 import java.io.FileReader;
 2   import java.io.FileWriter;
 3   import java.io.IOException;
 4   public class CopyFileDemo2 {
 5     public static void main(String[] args) throws IOException {
 6     // 封装数据源
 7     FileReader fr = new FileReader("d:\\a.txt");
 8     // 封装目的地
 9     FileWriter fw = new FileWriter("b.txt");
10     /* 一次一个字符
11     int ch = 0;
12     while ((ch = fr.read()) != -1) {
13     fw.write(ch);
14     }*/
15     // 一次一个字符数组
16     char[] chs = new char[1024];
17     int len = 0;
18     while ((len = fr.read(chs)) != -1) {
19     fw.write(chs, 0, len);
20     fw.flush();
21     }
22     // 释放资源
23     fw.close();
24     fr.close();
25     }
26     }

(8)高效字符流(字符流缓冲区)
  A:字符缓冲区输入流 -- BufferedReader
    从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
    可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了
  构造方法:
  public BufferedReader(Reader in):创建一个使用默认大小输入缓冲区的缓冲字符输入流。
  public BufferedReader(Reader in,int sz):创建一个使用指定大小输入缓冲区的缓冲字符输入流。
  成员方法:
  public String readLine():读取一个文本行。
  返回:包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
  B:字符缓冲区输出流 -- BufferedWriter
    将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
    可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。
  构造方法:
  public BufferedWriter(Writer out):创建一个使用默认大小输出缓冲区的缓冲字符输出流。
  public BufferedWriter(Writer out,int sz):创建一个使用给定大小输出缓冲区的缓冲字符输出流。
  成员方法:
  public void newLine():写入一个行分隔符。 注意:行分隔符字符串由系统属性定义,并且不一定是单个新行 ('\n') 符。
IO流小结
  IO流(字节流可以复制各种格式的文件,而字符流大多时候只用来复制文本文件)
  |--字节流
    |--字节输入流
    InputStream类
    (read():一次读取一个字节; read(byte[] bys):一次读取一个字节数组)
      |--FileInputStream类
      |--BufferedInputStream类
    |--字节输出流
    OutputStream类
    (write(int by):一次写一个字节; write(byte[] bys,int index,int len):一次写一个字节数组的一部分)
      |--FileOutputStream类
      |--BuffereOutputStream类
  |--字符流
    |--字符输入流
      Reader类
      (read():一次读取一个字符; read(char[] chs):一次读取一个字符数组)
        |--InputStreamReader类
          |--FileReader类
        |--BufferedReader类
          (String readLine():一次读取一个文本行字符串)
    |--字符输出流
      Writer类
      (write(int ch):一次写一个字符; write(char[] chs,int index,int len):一次写一个字符数组的一部分;write(String line):一次写一个字符串)
        |--OutputStreamWriter类
          |--FileWriter类
        |--BufferedWriter类
          (void newLine():写一个换行符;)
(9)操作基本数据类型的流(可以读写基本数据类型的数据,以写数据的类型方式对应读取数据,才能得到写入的数据)
   A:DataInputStream:数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。
    1)构造方法
      public DataInputStream(InputStream in):使用指定的底层 InputStream 创建一个 DataInputStream。
    2)成员方法(可以读取任意基本类型的值)
      char readChar():读取两个输入字节并返回一个 char 值。
      byte readByte():读取并返回一个输入字节。
      int readInt():读取四个输入字节并返回一个 int 值。
      double readDouble():读取八个输入字节并返回一个 double 值。
      ... Xxx readXxx(): 可以读取Xxx对应的字节数并返回一个类型Xxx的值。(Xxx可以是任意基本类型)
      String readLine():从输入流中读取下一文本行。
   B:DataOutputStream:数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中
    1)构造方法
      public DataOutputStream(OutputStream out):创建一个新的数据输出流,将数据写入指定基础输出流。
    2)成员方法(可以写出任意基本类型的值)
      public final void writeInt(int v):将一个int值以4-byte值形式写入基础输出流中,先写入高字节
      public final void writeChar(int v):将一个char值以2-byte值形式写入基础输出流中,先写入高字节
      public final void writeByte(int v):将一个 byte 值以 1-byte 值形式写出到基础输出流中。
      public final void writeLong(long v):将一个long值以8-byte值形式写入基础输出流中,先写入高字节
      ... writeXxx():可以写入任意基本类型数据
(10)内存操作流:用于处理临时存储信息的,程序结束,数据就从内存中消失
  A.操作字节数组(和InputStream/OutputStream类用法类似) -- 可以不释放资源
    ByteArrayInputStream
    public ByteArrayInputStream(byte[] buf):创建一个ByteArrayInputStream,使用buf作为其缓冲区数组
    ByteArrayOutputStream
    public ByteArrayOutputStream():创建一个新的 byte 数组输出流。
    public ByteArrayOutputStream(int size):创建一个新的 byte 数组输出流,它具有指定大小的缓冲区容量(以字节为单位)
    public byte[] toByteArray()创建一个新分配的 byte 数组。其大小是此输出流的当前大小,并且缓冲区的有效内容已复制到该数组中
  B.操作字符数组 -- 用法同上
    CharArrayReader
    CharArrayWrite
  C.操作字符串 -- 用法同上
    StringReader
    StringWriter
(11)打印流(输出流) -- 打印字节流/打印字符流
  public void print(char c):打印字符
  public void print(char[] s):打印字符数组。
  public void println(char x):打印字符,然后终止该行。
  public void println(char[] x):打印字符数组,然后终止该行
  public void println(String x): 打印 String,然后终止该行
注意:这里可以打印任意基本类型数据及字符数组和字符串
  字节打印流 PrintStream:打印的所有字符都使用平台的默认字符编码转换为字节
  字符打印流 PrintWriter:向文本输出流打印对象的格式化表示形式。
    public PrintWriter(Writer out,boolean autoFlush):创建新 PrintWriter。
    public PrintWriter(OutputStream out,boolean autoFlush):通过现有的OutputStream创建新的PrintWriter
    参数:autoFlush 如果为 true,则 println、printf 或 format 方法将刷新输出缓冲区;如果无 autoFlush 参数则创建的是不带自动刷新缓冲区的输出流
    public PrintWriter(String fileName):创建具有指定文件名称且不带自动行刷新的新 PrintWriter。
  启动自动刷新:
    PrintWriter pw = new PrintWriter(new FileWriter("pw2.txt"), true);
    调用 println、printf 或 format 方法将自动刷新输出缓冲区
    这时pw.println() 其实等价于:pw.write();pw.newLine();pw.flush();
  复制文本文件:
    读取数据 -- FileReader -- BufferedReader
    写出数据 -- FileWriter -- BufferedWriter -- PrintWriter
    //创建高效字符输入路对象(封装数据源)
    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();
  特点:
    A:只有写数据的,没有读取数据。只能操作目的地,不能操作数据源。
    B:可以操作任意类型的数据
    C:如果启用了自动刷新,能够自动刷新(在调用println()方法的时候,能够换行并刷新)
    D:可以直接操作文本文件
  问题:哪些流可以直接操作文件呢?
    查看API,如果其构造方法能够同时接收File和String类型的参数,一般都是可以直接操作文件的
(12)标准输入输出流(字节流)
  System 类的成员变量:
    public static final InputStream in; "标准"输入流。此流已打开并准备提供输入数据。默认输入设备是键盘。即System.in; 是从键盘获取数据的
    public static final PrintStream out; "标准"输出流。此流已打开并准备接受输出数据。默认输出设备是显示器。
  键盘录入数据的三种方式:
    A:main方法的args接收参数。
       java HelloWorld hello world java
    B:Scanner(JDK5以后的)对象
     Scanner sc = new Scanner(System.in);
     String s = sc.nextLine();
        int x = sc.nextInt()
    C:通过字符缓冲流包装标准输入流实现
     BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  输出语句的原理:
    System.out.println("hello") 等价于 PrintStream ps = System.out; ps.println("hello");
  使用字符流输出数据到控制台:
    把System.out用字符缓冲流包装一下使用
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    bw.write("hello"); //在控制台输出 hello
(13)随机访问流(RandomAccessFile类)
  可以按照文件指针的位置写数据和读数据。
  特点:
    RandomAccessFile 类不属于流,是Object类的子类;但它融合了InputStream和OutputStream的功能;支持对随机访问文件的读取和写入
  构造方法
    public RandomAccessFile(String name, String mode):创建向指定名称文件中读取和写入的随机访问文件流
    参数:mode - 访问模式(共四种,常用的一种为"rw",可读写) name - 文件名
      "r" 以只读方式打开。
      "rw" 以读取和写入方式打开。如果该文件尚不存在,则尝试创建该文件。
  成员方法:(可以读写任意基本类型的数据)
    public void seek(long pos):设置文件指针偏移量(距离文件开头的偏移量),在该位置发生下一个读取或写入操作。
    public long getFilePointer():返回此文件中的当前偏移量(文件指针)
    public final void writeInt(int v):按四个字节将 int 写入该文件,先写高字节。
    public final void writeChar(int v):按双字节值将 char 写入该文件,先写高字节
    public final void writeUTF(String str):使用 UTF-8 编码以与机器无关的方式将一个字符串写入该文件
    public final String readUTF():从此文件读取一个字符串
    public final char readChar():从此文件读取一个字符。
    public final String readLine():从此文件读取文本的下一行
    public final int readInt():从此文件读取一个有符号的 32 位整数
(14)合并输入流(SequenceInputStream类) -- 可以把多个输入流的数据写到一个输出流中
  概述:
  SequenceInputStream 表示多个输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,
直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。
  构造方法
  public SequenceInputStream(InputStream s1,InputStream s2):通过两个输入流对象创建合并输入流对象
  SequenceInputStream(将按顺序读取这两个参数,先读取s1,然后读取s2),以提供从此合并输入流读取的字节
  public SequenceInputStream(Enumeration<? extends InputStream> e):通过枚举创建合并输入流对象,该枚举运行时生成的对象类型为InputStream;合并输入流将按顺序读取由该枚举生成的输入流,
以提供从此合并输入流对象读取的字节。
  注意:枚举是包含自定义并且具有相同特性的数据的集合

 1 //把两个文件的内容写入到一个文本文件
 2 InputStream s1 = new FileInputStream("Byte.java");
 3 InputStream s2 = new FileInputStream("Data.java");
 4 //创建合并输入字节流对象
 5 SequenceInputStream sis = new SequenceInputStream(s1, s2);
 6 //创建缓冲输出字节流对象
 7 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Copy.java"));
 8 // 读写数据
 9 byte[] bys = new byte[1024];
10 int len = 0;
11 while ((len = sis.read(bys)) != -1) {
12 bos.write(bys, 0, len);
13 }
14 //释放资源
15 bos.close();
16 sis.close();

(15)序列化流/反序列化流
  序列化流 ObjectOutputStream:把 Java 对象按照流一样的方式写入文本文件或者在网络中传输。
  对象 --> 流数据(ObjectOutputStream) -- 写数据
    public ObjectOutputStream(OutputStream out):创建写入指定输出流的序列化流
    public final void writeObject(Object obj):将指定的对象写入 ObjectOutputStream。
    // 创建序列化流对象
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt"));
    // 创建自定义对象
    Person p = new Person("林青霞", 27);
    //将对象写入文本文件
    oos.writeObject(p);
   反序列化流 ObjectInputStream: 把文本文件中的流对象数据或者网络中的流对象数据还原成对象。
   流数据 --> 对象(ObjectInputStream) -- 读数据
    public ObjectInputStream(InputStream in):创建从指定 InputStream 读取的 ObjectInputStream
    public final Object readObject():从 ObjectInputStream 读取对象。
    // 创建反序列化对象
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oos.txt"));
    // 还原对象(从文本文件读取对象)
    Object obj = ois.readObject();
  如何实现序列化?
    类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。

     序列化接口没有方法或字段,仅用于标识可序列化的语义。这种接口被称为标记接口
注意:
  1)自定义实现序列化接口的时候,要自动生成一个ID值(点击黄色警告);无ID值的自定义类,当序列化写数据后修改自定义类,反序列化读数据时会报错。

有ID值的自定义类,当序列化后修改自定义类,反序列化时不会报错
  2)若自定义类中有多个成员变量,可使用transient关键字声明不需要序列化的成员变量。
未序列化的成员变量反序列化输出时,输出的是该成员变量的默认初值,而不是序列化时赋的值
(16)Properties集合 -- 是Hashtable的子类,属于Map集合。
  特点:
    1) Properties 类表示了一个持久的属性集。
    2) Properties 可保存在流中或从流中加载;可以和IO流相结合使用。
    3) 属性列表中每个键及其对应值都是一个字符串。
  特殊功能:
    public Object setProperty(String key,String value):添加元素(添加键 key 和值 value )
    public String getProperty(String key):获取元素,根据键 key 获取值
    public Set<String> stringPropertyNames():获取所有的键的集合
  注意:集合以键值对方式存储数据
  Properties集合和IO流的结合使用:
    把键值对形式的文本文件内容加载到集合中:
        public void load(Reader reader):把文件中的数据读取到集合中;按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)
        public void load(InputStream inStream):从输入流中读取属性列表(键和元素对)到集合;按简单的面向行的格式从输入字节流中读取属性列表
    把集合中的数据存储到文本文件中:
        public void store(Writer writer,String comments):将此 Properties 表中的属性列表(键和元素对)写入输出字符流。

      参数:comments - 属性列表的描述 -- 自定义一个字符串
     public void store(OutputStream out,String comments):将此 Properties表中的属性列表(键和元素对)写入输出流。

       参数:comments - 属性列表的描述 -- 自定义一个字符串

posted @ 2018-02-28 15:38  MyTeam  阅读(168)  评论(0编辑  收藏  举报