问题是出在objout.flush();
因为该方法需要将所写的Object的大小等头信息写入流中.
如果只写两个OBJ, 则文件内容为  头(2) + OBJ1 + OBJ2.
如果再写两个OBJ, 因为是APPEND,所以文件内容为头(2) + OBJ1 + OBJ2 + 头(2) + OBJ1 + OBJ2
你可以用ULTRAEDIT检验.

解决方案 »

  1.   

    确实是这样,但是我把flush()这句话去掉,还是如此啊,应怎么写呢?
      

  2.   

    做一个Vecter,在写之前,先把文件的内容读入Vecter,然后清空文件,先写入Vecter中的内容,再写入新的内容. 否则没有办法. flush()去掉是没有用的.
      

  3.   

    不知道这段文章对你有没有帮助许多 Java 书籍已对利用 Java 1.1 
    对象输入/输出流在网上发送运行时对象这一问题作了讨论。但对于需要将对象传递到多个目标(“广播”)或使用无连接协议的应用程序而言,数据报可能比基于流的套接字更可取。 
    如果对象比较复杂,则将对象打包(即“序列化”)在一个数据报包中可能很困难。这篇 Java 技巧说明如何使用 Java 
    数据报套接字在网上传送对象,而且无须编写任何专用的序列化代码。 
    Java 1.1 吸引人的特性之一就是新增了 ObjectInputStream 和 ObjectOutputStream 这两个类。有了这个新的 
    API(ObjectOutputStream 类中的 writeObject(Object o) 方法和 ObjectInputStream 类中的 
    object readObject()),您就可以随时获取运行对象的快照,而不管它的对象图有多复杂。因为这种快照是通过 ObjectOutputStream 
    类(OutputStream 类的子类)提供的,所以您很容易将它包装在其他输出流中,从而实现所需的任何功能(如 FileOutputStream)。 
    Java 1.1 中提供的这些新类使得在网上传输运行对象成为可能。为此,该对象以及那些被引用的对象必须可序列化 -- 即能够转换为字节流。幸运的是,在 Java 
    1.1 中,多数内建的类都是可序列化的。但是,某些类是不可序列化的(Object 类就是一个典型的例子)。不过别担心。如果您的类继承自不可序列化的类,您还可以用 
    ObjectOutputStream 类中的 defaultWriteObject() 方法实现序列化,随后还可用 ObjectInputStream 类中的 
    defaultReadObject() 方法解除序列化。 一旦进行了序列化,对象就可在网上传输了。以下示例说明生成可序列化对象并通过流套接字发送它的方法: //对象输出
    import java.net.*; 
    import java.io.*;//要发送的类样例:Factory
    class Factory implements Serializable
    {
    private void writeObject(ObjectOutputStream out) throws IOException
    {
    out.defaultWriteObject();
    }private void readObject(ObjectInputStream in)
    throws IOException, ClassNotFoundException
    {
    in.defaultReadObject();
    }
    }public class ShowObjOutput
    {
    public static void main(String[] arg)
    {
    try
    {
    ObjectOutputStream os;
    Socket sock = new Socket("panda.cs.uno.edu", 6000); //panda 为主机名
    Factory fa = new Factory();os = new ObjectOutputStream( new
    BufferedOutputStream(sock.getOutputStream()));
    os.writeObject(fa);
    }
    catch (IOException ex)
    {}
    }
    }
    下一示例说明了 ObjectInputStream 如何从流套接字接收对象://对象输入
    import java.net.*; 
    import java.io.*;public class ShowObjInput
    {
    public static void main(String[] arg)
    {
    try
    {
    ObjectInputStream is;
    ServerSocket servSock = new ServerSocket(6000);
    Sock sock;sock = servSock.accept();
    is = new ObjectInputStream( new
    BufferedInputStream(sock.getInputStream()));
    Factory o = (Factory)is.readObject();
    }
    catch (IOException ex)
    {}
    }
    }
    除了紧密耦合的套接字之外,Java 还提供了 DatagramSocket 
    类来支持无连接的数据报通信。我们可以使用数据报通信完成对象输入/输出吗?完成此功能不象使用流套接字那么简单?问题在于 DatagramSocket 
    未连接到任何流;为了执行发送和接收操作,DatagramSocket 使用一个字节数组作为参数。可以想像,为了构造数据报包,对象必须转换成字节数组。如果对象涉及到一个复杂的对象图,这种转换可能极难完成。以前发表的许多文章讨论了实现对象序列化的方法 -- 
    即将 Java 对象打包(序列化)成字节流以及将字节流解包为 Java 对象。然而,由于对象图可能很复杂,则将常规对象图转换成字节数组可能需要编写大量的代码。 那么,如何避免编写复杂的打包代码呢?以下提供了一种利用数据报包传输对象的方法,而且无需编写打包代码。 
    上图说明了使用数据报传输对象时的数据流。按以下给出的七个步骤,您就能实现这个数据流,它可传输任何类型的对象,myObject。 
    第一步。准备:通过实现 Serializable 接口使您的对象(比方说 myObject)可序列化。 第二步。创建 ByteArrayOutputStream 对象,比方说,名为 baoStream。 第三步。用 baoStream 构造一个 ObjectOutputStream 对象,比方说 ooStream。 第四步。通过调用 ooStream 的 writeObject() 方法将对象 myObject 写入 baoStream 中。 第五步。使用 baoStream 的 toByteArray() 方法从 baoStream 中检索字节数组缓冲区。 第六步。使用由第五步检索到的数组缓冲区构造 DatagramPacket,比方说 dPacket。 第七步。通过调用 DatagramSocket 的 send() 方法发送 dPacket。
    要接收对象,以逆序完成以上所列各步,用 ObjectInputStream 代替 ObjectOutputStream,同时用 
    ByteArrayInputStream 代替 ByteArrayOutputStream。 当用套接字编程时,sendTo 是无连接协议中使用的一个标准函数。为了能够传输对象,我重写了这个函数。以下代码示例展示了如何在 Sender 类中实现 send 
    方法: import java.io.*;
    import java.net.*; public class Sender
    {
    public void sendTo(Object o, String hostName, int desPort)
    {
    try
    {
    InetAddress address = InetAddress.getByName(hostName);
    ByteArrayOutputStream byteStream = new
    ByteArrayOutputStream(5000);
    ObjectOutputStream os = new ObjectOutputStream(new
    BufferedOutputStream(byteStream));
    os.flush();
    os.writeObject(o);
    os.flush();// 检索字节数组
    byte[] sendBuf = byteStream.toByteArray();
    DatagramPacket packet = new DatagramPacket(
    sendBuf, sendBuf.length, address, desPort);
    int byteCount = packet.getLength();
    dSock.send(packet);
    os.close();
    }
    catch (UnknownHostException e)
    {
    System.err.println("Exception: " + e);
    e.printStackTrace ();
    }
    catch (IOException e)
    { e.printStackTrace(); }
    }
    }
    以下代码清单说明了如何在 Receiver 类中实现 receive 方法。recvObjFrom 
    方法是供接收者接收对象的。您应在您的代码中包含此方法以接收运行时对象。 import java.io.*;
    import java.net.*; public class Receiver
    {
    public Object recvObjFrom()
    {
    try
    {
    byte[] recvBuf = new byte[5000];
    DatagramPacket packet = new DatagramPacket(recvBuf,
    recvBuf.length);dSock.receive(packet);
    int byteCount = packet.getLength();ByteArrayInputStream byteStream = new
    ByteArrayInputStream(recvBuf);ObjectInputStream is = new
    ObjectInputStream(new BufferedInputStream(byteStream));
    Object o = is.readObject();
    is.close();
    return(o);
    }
    catch (IOException e)
    {
    System.err.println("Exception: " + e);
    e.printStackTrace ();
    }
    catch (ClassNotFoundException e)
    { e.printStackTrace(); }return(null);
    }
    }
    人们可能会担心字节数组的大小 -- 因为当您构造 ByteArrayOutputStream 或 ByteArrayInputStream 
    时,您必须指定数组的大小。既然您不知道运行时对象的大小,您就很难指定其大小。运行时对象的大小通常是不可预知的。幸运的是,Java 的 
    ByteArrayInputStream 和 ByteArrayOutputStream 类可根据需要自动扩展其大小。 小结
    通过利用 Java 的内建序列化代码,我阐述了一种使用数据报包传输对象的方法。正如您所见,技巧就是使用字节数组流将对象流化为字节数组
      

  4.   

    to helpall
    不知道你关于flush的论述是那里来的。
    没看到api文档有这说法。
    public void flush()
               throws IOExceptionFlushes the stream. This will write any buffered output bytes and flush through to the underlying stream.今天刚好也在找这方面的资料。
    关于楼主的问题。没有看到你再写2遍,写后两个对象的代码。
    不过如果你是close() 后再写,就等于是从这个文件的头上重新写了。
      

  5.   

    不过如果你是close() 后再写,就等于是从这个文件的头上重新写了。不是啊
    FileOutputStream fileout = new FileOutputStream("D:\\JBuilder6\\samples\\Welcome\\defaultroot\\030101.news",true);
    这句话就是追加啊