黑马程序员------java -io操作

                                       ------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

对程序语言设计者来说,设计一个令人满意的I/O系统,是极其艰巨的一个任务。——《Think in java》

关于I/O系统的设计,话再多的时间去研究也不足为怪,这里仅仅我再初步学习I/O时的点点滴滴的记录。


一、File类

  File类是File类是java.io包中唯一处理磁盘文件和目录的类。它提供的方法都是与平台无关的,
   通过使用File类提供各种方法能够创建、删除文件和目录,或者获取磁盘上指定的文件和目录的相关信息。

package com.tai.io;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;

public class FileDemo
{
    /**
     * File类是java.io包中唯一处理磁盘文件和目录的类。它提供的方法都是与平台无关的,
     * 通过使用File类提供各种方法能够创建、删除文件和目录,或者获取磁盘上指定的文件和目录的相关信息。
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException
    {
        File file = new File("E:/文件夹");
        if(file.mkdir())
        {
            System.out.println("文件夹已创建!");
        }
            
        File file2 = new File("E:/文件夹/文件.txt");
        if(file2.createNewFile())
        {
            System.out.println("文件已经创建!");
        }
        
        getInfor(file2);
        
        if(file2.delete())
        {
            System.out.println("文件已删除!");
        }
        
        File Dir = new File("C:"+File.separator+"abc");//separator 文件分割符这样写便于代码跨平台,更加健壮!
        fFilter(Dir);
    }
    
    /*
     *获取相关信息
     */
    private static void getInfor(File file)
    {
        System.out.println("文件名"+file.getName());
        System.out.println("文件父路径"+file.getParent());
        System.out.println("文件的绝对路径"+file.getAbsolutePath());
        System.out.println("所在磁盘的大小"+file.getTotalSpace()/(1024*1024*1024)+"GB");
        System.out.println("所在磁盘的可用空间"+file.getUsableSpace()/(1024*1024*1024)+"GB");
        System.out.println("是否是文件"+file.isFile());
        System.out.println("是否是文件夹"+file.isDirectory());
        System.out.println("是否是隐藏文件"+file.isHidden());
        System.out.println("是否可读"+file.canRead()+"  是否可写"+file.canWrite()+"  是否可执行"+file.canExecute());
    }
    
    /*
     * FilenameFilter 过滤接口 此处用内部类实现FileFilter的accept()方法
     * FilenameFilter和FileFilter类似,也提供文件过滤功能
     * 性能上FilennameFilter较FileFilter效率稍高
     */
    private static void fFilter(File file)
    {
        File[] files = file.listFiles(new FileFilter()
        {
            @Override
            public boolean accept(File pathname)
            {
                if(pathname.isFile()&&pathname.getName().endsWith(".txt"))
                {
                    return true;
                }
                return false;
            }
        });
        System.out.println("该目录下的所有文本文件");
        for(File f:files)
        {
            System.out.println(f.getName());
        }
    }
    
}
运行结果:
文件夹已创建!
文件已经创建!
文件名文件.txt
文件父路径E:\文件夹
文件的绝对路径E:\文件夹\文件.txt
所在磁盘的大小84GB
所在磁盘的可用空间31GB
是否是文件true
是否是文件夹false
是否是隐藏文件false
是否可读true  是否可写true  是否可执行true
文件已删除!
该目录下的所有文本文件
b.txt
新建文本文档 (2).txt
新建文本文档.txt

二、字节流

  计算机中的数据都是以字节为单位进行处理的,这类的数据保存文件也成为“二进制文本”,在Java中对这些文本的操作就是要使用Java的字节流对象。

InputStream和OutputStream分别是输入与输出字节流,它们都是抽象类型的,都不能实例化,它们在I/O包中的顶层,作为了众多字节流的父类。

Java中的字节流有很多,这是我写的几个常用的字节流Demo.

FileInputStream/FileOutputStream

FileInputStream与FileOutputStream 被称为文件流,是最常见的字节流。用于对磁盘文件的读写操作。
 * File类不只能创建、删除、获取文剪信息,但是不能打开和读写文件。FileInputStream与FileOutoutStream就是用于读写文件的
 * FileInputStream 的构造方法
 *   FileInputStream fis = new FileInputStream("c:/abc");
  File file = new File("c:/abc");
  FileInputStream fis = new FileInputStream(file);
  为了简化常用:
  FileInputStream fis = new FileInputStream(new File("c:/abc"));

package com.tai.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileInputStreamDemo
{
/**
 * FileInputStream与FileOutputStream 被称为文件流,是最常见的字节流。用于对磁盘文件的读写操作。
 * File类不只能创建、删除、获取文剪信息,但是不能打开和读写文件。FileInputStream与FileOutoutStream就是用于读写文件的
 * FileInputStream 的构造方法
 *         FileInputStream fis = new FileInputStream("c:/abc");
        File file = new File("c:/abc");
        FileInputStream fis = new FileInputStream(file);
        为了简化常用:
        FileInputStream fis = new FileInputStream(new File("c:/abc"));
 * @throws IOException 
 */
    public static void main(String[] args) throws IOException
    {
        FileInputStream fis = new FileInputStream(new File("C:/abc/Demo.txt"));
        FileInputStream fis2 = new FileInputStream(new File("C:/abc/b.txt"));
        int b=0,len=0;
        System.out.println("使用read()方法,每次读一个字节:");
        //使用循环,每次读入一个字节,直到文件结尾。
        while((b=fis.read())!=-1)
        {
            System.out.print((char)b);
        }
        fis.close();
        System.out.println("\n使用read(byte[] b)的方法,读取文件存入字符数组中");
        //读取文件,直到结尾,存入byte数组中,打印。
        byte[] bt = new byte[516];
        while(-1!=(len=fis2.read(bt,0,516)))
        {
            String str = new String(bt,0,len);这里需要特别注意的是  从0到len  len是实际的长度可能不到516 、
            System.out.print(str);
        }
        fis2.close();
        
    }
  
}


运行结果:
使用read()方法,每次读一个字节:
this is a FileInputDemo.
使用read(byte[] b)的方法,读取文件存入字符数组中
回家过年,这本是很简单的四个字,却是许许多多游子一年中的期盼,当然,这也包括那些在外求学的莘莘学子们。

在外瓢泼久了,多想回到家乡看看为我们牵挂的父母亲人。曾经多少个日日夜夜想及这些,我们可以做的只是一壶浊酒而后在心底默默的祝福与思念。

“举头望明月,低头思故乡”一年到头,隐藏在我们心底的除了深深的牵挂还剩下什么呢?一年到头,又有多少父母无时无刻不在思念着远方的儿女?

记得还小的时候我们是多么的喜欢过年,有新衣服穿、有压岁钱拿,好多好吃好玩的,还不用担心作业是否已经完成。而今我们盼望着过年,却只是那短暂的团聚,可以陪父母陪亲人说说心里的话。同时我们又多么地害怕,害怕父母那期望的眼神,尤其是害怕看见父母那满头乌发渐渐泛白,甚至脱落。虽然我知道,人没有不会老的,但看见父母脸上渐添的皱纹,和那渐渐泛白的乌发,心中总会有一种心酸的感觉。

FileOutputStream

     * FileOutputStream类是用于向磁盘文件写入字符数据的输出类
     * 当想磁盘某个文件写入时如果文件不存在它不会向FileInputStream那样抛异常,而是创建一个新的文件。
     * 构造方法与FileInputStream类似,但是有的会多个参数:
     * FileOutputStream fos = new FileOutputStream(File file,boolean append)
     * append  是否想文件尾部追加  true 在该文件的结尾追加内容,flase将清除原有的内容,添加新的内容。

package com.tai.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutputStreamDemo
{
    /**
     * 本程序的功能是将一个文本中的内容复制到另一个文本中。
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException
    {
        FileInputStream fis = new FileInputStream(new File("C:/abc/Demo.txt"));
        FileOutputStream fos = new FileOutputStream(new File("C:/abc/Demo2.txt"),false);
        int b= 0,len=0;
        byte[] bt = new byte[512];
        
        while(-1!=(len=fis.read(bt,0,512) ) )
        {
            fos.write(bt,0,len);
        }
        System.out.println("已经吧Demo.txt中的内容复制到了Demo2.txt中!!");
        fos.close();
        fis.close();
       
        FileOutputStream fos2 = new FileOutputStream(new File("C:/abc/Demo3.txt"),false);
        writein(fos2,"hello world!");
        System.out.println("已经hello world写入到了文件C:/abc/Demo3.txt中");
    }
    
    /*
     * 简单的向文件写入字符串
     */
    private static void writein(FileOutputStream fos,String str)
    {
        byte[] b  = str.getBytes();
        try
        {
            fos.write(b);
            fos.close();
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
}


执行结果:

  已经吧Demo.txt中的内容复制到了Demo2.txt中!!
      已经hello world写入到了文件C:/abc/Demo3.txt中



java.io包中提供了FilterInputStream和FilterOutputStream类分别对其他输入输出流进行特殊的处理,它们在
  * 读/写数据的同时还能够对数据进行特殊的处理。另外它们还提供了同步机制,是的某一时刻之后一个线程可以访问输入/输出流。
  * FilterInputStream/FilterOutputStream都是抽象类。
  * FilterInputStream有三个子类:BufferedInputStream、DataInputStream、PushbackInputStream
  * FilterOutputStream也有三个子类:BufferedOutputStream、DataOutoutStream、PrintStream
  * 
  * 使用过滤字节流的时候,必须先制定节点流对象处理底层的数据,然后把节点流对象作为过滤流对象的实参使用。即把过滤流对象连接到某个输入/输出节点流对象上如下:
  * FileInputStream fis = new FileInputStream(new File("c:/abc.txt"));
  * DataInputSream dis = new DataInputStream(fis);

 

一、BufferedInputStream/BufferedOutputStream


  * BufferedInputStream/BufferedOutputStream 是缓冲字节流,它引入了针对内存缓冲区的操作,从而提高了读写数据的效率。
  * 缓冲区的默认大小为32字节,也可以指定缓冲区的大小。
  * 相应的构造的方法
  * BufferedInputStream(InputStream in) 这里的in只要是继承自InputSream的对象都可以作为参数
  * BufferedInputStream(InputStream in,int size)
  * BufferedOutputStream与上面的对应。

Demo:使用BufferedInputStream/BufferdeOutputStream完成文件的复制。

package com.tai.io;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class BufferedInputStreamDemo
{
    /**
     * java.io包中提供了FilterInputStream和FilterOutputStream类分别对其他输入输出流进行特殊的处理,它们在
     * 读/写数据的同时还能够对数据进行特殊的处理。另外它们还提供了同步机制,是的某一时刻之后一个线程可以访问输入/输出流。
     * FilterInputStream/FilterOutputStream都是抽象类。
     * FilterInputStream有三个子类:BufferedInputStream、DataInputStream、PushbackInputStream
     * FilterOutputStream也有三个子类:BufferedOutputStream、DataOutoutStream、PrintStream
     * 
     * 使用过滤字节流的时候,必须先制定节点流对象处理底层的数据,然后把节点流对象作为过滤流对象的实参使用。即把过滤流对象连接到某个输入/输出节点流对象上
     * 
     * FileInputStream fis = new FileInputStream(new File("c:/abc.txt"));
     * DataInputSream dis = new DataInputStream(fis);
     * BufferedInputStream/BufferedOutputStream 是缓冲字节流,它引入了针对内存缓冲区的操作,从而提高了读写数据的效率。
     * 缓冲区的默认大小为32字节,也可以指定缓冲区的大小。
     * 相应的构造的方法
     * BufferedInputStream(InputStream in) 这里的in只要是继承自InputSream的对象都可以作为参数
     * BufferedInputStream(InputStream in,int size)
     * BufferedOutputStream与上面的对应。
     */
    public static void main(String[] args) throws IOException
    {
        FileInputStream fis = new FileInputStream(new File("c:/曲婉婷 - 没有什么不同 [mqms].mp3"));
        BufferedInputStream bis = new BufferedInputStream(fis,1024);
        FileOutputStream fos = new FileOutputStream(new File("c:/没有什么不同.mp3"));
        BufferedOutputStream bos = new BufferedOutputStream(fos,1024);
        
        byte[] buffer = new byte[1024];
        int len =0;
        while(-1!=(len=bis.read(buffer,0,1024)))
        {
            //将buffer中从fis读取来的数据写入到bos中
            bos.write(buffer,0,len);
        }
        bos.flush();//最近一次读取的数据可能达不到1024字节,这里强制清空缓冲区\
        System.out.println("已经将c:/曲婉婷 - 没有什么不同 [mqms].mp3复制到c:/没有什么不同.mp3");
        bos.close();
        fos.close();
    }
}

二、DataInputStream和DataOutputStream

 * java.io包中还有连个接口DataInput和DataOutput,这两个接口设计了较高级的数据输入输出方式,除了可以处理字节个字节数组外
  * 还可以处理  int、float、boolean等基本的数据类型,这些数据在文件中的表示方式和它们在内存中的方式一样,无序转换,它们相应的提供了
  * 很多处理基本数据类型的方法,如:DataInput提供了read()、readInt()、readByte()等DataOutput提供了write()、writeInt()、
  * writeFloat()、writeChar()等 ....
  * 
  * 而数据流类 DataInputStream和DataOutputStream分别实现了DataInput和DataOutput接口。它们以统一的方式向输入流中写入boolean、int、long
  * double等基本的数据类型,并且还可以把基本的数据类型取出来,同时它们也有针对字符串的读写方法

Demo:

package com.tai.io;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;

public class DataInputStreamDemo
{
    /**
     * java.io包中还有连个接口DataInput和DataOutput,这两个接口设计了较高级的数据输入输出方式,除了可以处理字节个字节数组外
     * 还可以处理  int、float、boolean等基本的数据类型,这些数据在文件中的表示方式和它们在内存中的方式一样,无序转换,它们相应的提供了
     * 很多处理基本数据类型的方法,如:DataInput提供了read()、readInt()、readByte()等DataOutput提供了write()、writeInt()、
     * writeFloat()、writeChar()等 ....
     * 
     * 而数据流类 DataInputStream和DataOutputStream分别实现了DataInput和DataOutput接口。它们以统一的方式向输入流中写入boolean、int、long
     * double等基本的数据类型,并且还可以把基本的数据类型取出来,同时它们也有针对字符串的读写方法
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException
    {
        FileOutputStream fos = new FileOutputStream(new File("C:/abc/a.txt"));
        DataOutputStream dos = new DataOutputStream(fos);
        Scanner scan = new Scanner(System.in);
        System.out.println("请输入数据: ");
        
        dos.writeBoolean(scan.nextBoolean());
        dos.writeByte(scan.nextInt());
        dos.writeFloat(scan.nextFloat());
        dos.writeShort(scan.nextInt());
        dos.writeChar('A');
        dos.close();
        
        FileInputStream fis = new FileInputStream(new File("C:/abc/a.txt"));
        DataInputStream dis = new DataInputStream(fis);
        System.out.println("读取Boolean数据 \t" + dis.readBoolean());
        System.out.println("读取Byte数据 \t" + dis.readByte());
        System.out.println("读取Float数据 \t" + dis.readFloat());
        System.out.println("读取Short数据 \t" + dis.readShort());
        System.out.println("读取Char数据 \t" + dis.readChar());
        dis.close();
        
    }
}


管道字节流


 * 管道用来把程序、线程或程序块的输出连接到另一个程序、线程或者程序块作为它的输入。
 * java.io提供了类PipedInputSteramh和PipedOutputStream 作为管道的输入/输出流。
 * 管道输入流作为一个通信管道接收端,管道输出流作为发送端。管道流必须是输入流输出流同时并用,即在使用管道前,两者必须进行连接。
 * 无论PipedInputStream还是PipdeOutputStream类都提供了connect()方法可以使用connect()方法建立一个管道进行数据传输。
 * 管道输入/输出流可以用两种方式进行连接,一种方式是使用connect()方法:
 *   PipedInputStream pis  = new PipedInputStream();
 *  PipedOutputStream pos = new PipedOutputStream();
 *  pis.connect(pos);
 *  pos.connect(pis);
 *  另外一种是直接使用构造方法进行连接:
 *  PipedInputStream pis = new PipedInputStream();
 *  PipedOutputStream pos = new PipedOutputStream(pis);
 *   
 *  除了connect()方法PipedInputStream类还继承了InputStream类的read()方法。另外又增加了receive()方法
 *  PipedOutputStream类也继承自OutputStream类的write()方法。

Demo1:

package com.tai.io;

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

public class PipedStreamDemo
{
/**
 * 管道字节流
 * 管道用来把程序、线程或程序块的输出连接到另一个程序、线程或者程序块作为它的输入。
 * java.io提供了类PipedInputSteramh和PipedOutputStream 作为管道的输入/输出流。
 * 管道输入流作为一个通信管道接收端,管道输出流作为发送端。管道流必须是输入流输出流同时并用,即在使用管道前,两者必须进行连接。
 * 无论PipedInputStream还是PipdeOutputStream类都提供了connect()方法可以使用connect()方法建立一个管道进行数据传输。
 * 管道输入/输出流可以用两种方式进行连接,一种方式是使用connect()方法:
 *         PipedInputStream pis  = new PipedInputStream();
 *        PipedOutputStream pos = new PipedOutputStream();
 *        pis.connect(pos);
 *        pos.connect(pis);
 *        另外一种是直接使用构造方法进行连接:
 *        PipedInputStream pis = new PipedInputStream();
 *        PipedOutputStream pos = new PipedOutputStream(pis);
 *         
 *     除了connect()方法PipedInputStream类还继承了InputStream类的read()方法。另外又增加了receive()方法
 *     PipedOutputStream类也继承自OutputStream类的write()方法。    
 * @throws IOException 
 */
    
    public static void main(String[] args) throws IOException
    {
        int ch1 = 0;
        PipedInputStream pis = new PipedInputStream();
        PipedOutputStream pos = new PipedOutputStream(pis);
        //也可以使用connect()方法
         //    PipedOutputStream pos = new PipedOutputStream();
         //        pos.connect(pis);
        System.out.println("请输入一个字符,按#结束程序!");
        while((ch1 = System.in.read())!='#')
        {
            pos.write(ch1);
            System.out.println((char)pis.read());
        }
    }
}

PipedInputStream 和PipedOutStream常与线程连用,已达到在不同线程间的通讯:

package com.tai.io;

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

public class PipedStreamDemo2
{
    public static void main(String[] args) throws IOException
    {
        PipedInputStream pis = new PipedInputStream();
        //实例管道输出流并与上面的管道输入流连接
        PipedOutputStream pos = new PipedOutputStream(pis);
        
        new Thread(new InputThread(pis)).start();
        new Thread(new OutputThread(pos)).start();
    }
}

class InputThread implements Runnable
{

    private PipedInputStream pis;
    public InputThread(PipedInputStream in)
    {
        this.pis = in;
    }
    
    @Override
    public void run()
    {
        byte[] buffer = new byte[1024];
        int len = 0;
        try
        {
            len = pis.read(buffer);
            
            String str = new String(buffer,0,len);
            
            System.out.println("管道输入流作为接收端,接受来自管道输出流发送的内容。  内容是:    "+ str);
            pis.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        
    }
}

class OutputThread implements Runnable
{
    private PipedOutputStream pos;
    public OutputThread (PipedOutputStream out)
    {
        this.pos = out;
    }
    @Override
    public void run()
    {
        try
        {
            pos.write("管道输出流作为发送端向管道输入流发送内容".getBytes());
            pos.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
    
}

对象持久化(Persistence)就是 将对象保存到磁盘文件或者网络中,保存对象的过程实质上就是对象持久化的过程。
* 也就是记录对象的状态以便于将来具有再生的能力。 Java提供了对象流以实现对象的输入输出,也就是实现对象的持久化。
* 需要注意的是在使用对象流之前必须要将该对象序列化。所谓的序列化就是将对象的状态转化成字节流,并且以后可以通过这些值 再生成相同状态的对象。
* 简单来说序列化就是一种用来处理对象流的机制,而对象流也就是将对象的内容进行流化,我们可以对流化后的对象进行读取操作,
* 也可以将流化后的对象传输于网络之间。

* 对象序列化,只需要被序列化的类实现Serializable接口就可以了。
* Serializable接口中没有任何的方法,让一个类实现该接口只是为了标注该对象是可以被序列化的,然后就可以对该对象进行持久化。

* 注意: 序列化只能保存对象的实例变量,但不能保存类的任何方法和类变量,并且保存的只是变量的值。 对于任何修饰符都不能保存。
* 有些类型的变量是瞬时的,这样的对象也是无法保存的,如:线程对象、或流对象。对于这样的变量,必须用transient关键字标明,否则编译器将报错。

* 任何被transient标明的成员变量,将不被保存。
* 考虑到序列化可能涉及对象保存在磁盘上或者网络上,对于一些保密的数据就要加上transient关键字。


* 对象序列化之后,必须与一定的对象输入/输出流联系起来,通过对象输出流将对象的状态保存下来,再通过对象输入流将对象的状态恢复。
* java提供了ObjectInputStream
* 类和ObjectOutputStream类分别实现了ObjectInput和ObjectOutput。
* ObjectOutput接口用writeObject
* ()方法,可以将对象的状态保存到输出流中。而ObjectInput接口用readObject()方法以从输入流中读入一个对象。
*
package com.tai.io;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class PersistenceDome
{
    /**
     * 对象持久化(Persistence)就是 将对象保存到磁盘文件或者网络中,保存对象的过程实质上就是对象持久化的过程。
     * 也就是记录对象的状态以便于将来具有再生的能力。 Java提供了对象流以实现对象的输入输出,也就是实现对象的持久化。
     * 需要注意的是在使用对象流之前必须要将该对象序列化。所谓的序列化就是将对象的状态转化成字节流,并且以后可以通过这些值 再生成相同状态的对象。
     * 简单来说序列化就是一种用来处理对象流的机制,而对象流也就是将对象的内容进行流化,我们可以对流化后的对象进行读取操作,
     * 也可以将流化后的对象传输于网络之间。
     * 
     * 对象序列化,只需要被序列化的类实现Serializable接口就可以了。
     * Serializable接口中没有任何的方法,让一个类实现该接口只是为了标注该对象是可以被序列化的,然后就可以对该对象进行持久化。
     * 
     * 注意: 序列化只能保存对象的实例变量,但不能保存类的任何方法和类变量,并且保存的只是变量的值。 对于任何修饰符都不能保存。
     * 有些类型的变量是瞬时的,这样的对象也是无法保存的,如:线程对象、或流对象。对于这样的变量,必须用transient关键字标明,否则编译器将报错。
     * 
     * 任何被transient标明的成员变量,将不被保存。
     * 考虑到序列化可能涉及对象保存在磁盘上或者网络上,对于一些保密的数据就要加上transient关键字。
     * 
     * 
     * 对象序列化之后,必须与一定的对象输入/输出流联系起来,通过对象输出流将对象的状态保存下来,再通过对象输入流将对象的状态恢复。
     * java提供了ObjectInputStream
     * 类和ObjectOutputStream类分别实现了ObjectInput和ObjectOutput。
     * ObjectOutput接口用writeObject
     * ()方法,可以将对象的状态保存到输出流中。而ObjectInput接口用readObject()方法以从输入流中读入一个对象。
     * 
     * @throws Exception
     */
    public static void main(String[] args) throws Exception
    {
        Person p = new Person("张三", "Mauiie", "男");
        Person p2 = new Person("p2", "Mauiie", "男");
        Person p3 = new Person("p3", "Mauiie", "男");
        Student s = new Student("孙俪", "Mauiie", "女");
        Person temp = null;
        Person temp2 = null;
        Student stemp = null;
        FileOutputStream fos = new FileOutputStream("c:/data.dat");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(p);
        oos.writeObject(p2);
//        oos.writeObject(p3);
        oos.writeObject(s);
        oos.close();
        System.out.println("已经将p和s对象写入到了 c:/data.dat");

        FileInputStream fis = new FileInputStream("c:/data.dat");
        ObjectInputStream ois = new ObjectInputStream(fis);

        temp = (Person) ois.readObject();
        temp2 = (Person) ois.readObject();
        stemp = (Student) ois.readObject();
        
        ois.close();
        System.out.println(temp.toString());
        System.out.println(stemp.toString());
        System.out.println(temp2.toString());
    }
}

class Person implements Serializable
{
    String Pname;
    transient String Pid;
    String Psex;

    public Person(String name, String ID, String sex)
    {
        this.Pname = name;
        this.Pid = ID;
        this.Psex = sex;
    }

    public String toString()
    {
        return "Name  " + Pname + "  ID  " + Pid + "  sex  " + Psex;
    }
}

class Student implements Serializable
{
    String Sname;
    transient String Sid;
    String Ssex;

    public Student(String name, String ID, String sex)
    {
        this.Sname = name;
        this.Sid = ID;
        this.Ssex = sex;
    }

    public String toString()
    {
        return "这是Student对象      " + "Name  " + Sname + "  ID  " + Sid
                + "  sex  " + Ssex;
    }
}

ObjectInputStream/ObjectOutputStream

运行结果:

已经将p和s对象写入到了 c:/data.dat
Name  张三  ID  null  sex  男
这是Student对象      Name  孙俪  ID  null  sex  女
Name  p2  ID  null  sex  男

值得注意的是:

使用缺省的serializetion的实现时,一个ObjectOutputStream的构造和一个ObjectInputStream的构造必须一一对应。

ObjectOutputStream的构造函数会向输出流中写入一个标识头,而ObjectInputStream会首先读入这个标识头。因此,多次以追加方式向一个文件中写入object时,该文件将会包含多个标识头。

所以用ObjectInputStream来deserialize这个ObjectOutputStream时,将产生StreamCorruptedException。
一种解决方法是可以构造一个ObjectOutputStream的子类,并覆盖writeStreamHeader()方法。被覆盖后的writeStreamHeader()方法应判断是否为首次向文件中写入object?

若是,则调用super.writeStreamHeader();若否,即以追加方式写入object时,则应调用ObjectOutputStream.reset()方法。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值