将对象附加到二进制文件

时间:2011-01-10 11:22:31

标签: java

请您使用以下方法:

public static void writeToBinary(Object obj, String filename) 
{
 ObjectOutputStream oos = null;
 try {
  oos = new ObjectOutputStream(new FileOutputStream(filename));
  oos.writeObject(obj);
 } catch (Exception e) {
  e.printStackTrace();
 }  finally{
  try{
   if (oos != null) oos.close ();
  }catch (Exception e){
   e.printStackTrace();
  }
 }
}

如您所见,该方法将对象写入二进制文件。

但是现在你想重写相同的方法以允许将对象附加到同一个文件 好的,你看一下java文档,你会发现你必须在FileOutputStream中添加一个值为true的参数:

oos = new ObjectOutputStream(new FileOutputStream(filename, true));

你编译但是,哎呀!似乎它继续覆盖文件。

好吧,问题就开始了。在google中搜索后,您会发现必须使用 SAME ObjectOutputStream将对象附加到同一文件中。你希望有一个函数,每次调用它时,它都会追加一个对象。即:

writeToBinary("a", filename);
writeToBinary("b", filename);

但正如我之前所说,你必须使用相同的ObjectOutputStream。

解决方案1:

ObjectOutputStream out = getOutputStream (filename);
writeToBinary("a", out);
writeToBinary("b", out);
writeToBinary("c", out);
out.close ();

这非常难看,因为我想隐藏流的用法。

还有其他解决方案吗?

编辑:该方法是静态的。它位于实用程序类中,所有方法都是静态的。

编辑2:解决了! Appending to an ObjectOutputStream。请参阅我的问题的已接受答案。 感谢。

4 个答案:

答案 0 :(得分:8)

解决。

import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

public class Test{
    private static String filename = "test";

    public static void main(String[] args) {
        writeToBinary (filename, "a", true);
        writeToBinary (filename, "b", true);
        writeToBinary (filename, "c", true);
        readFromBinaryFile (filename);
    }

    public static void writeToBinary (String filename, Object obj, boolean append){
        File file = new File (filename);
        ObjectOutputStream out = null;

        try{
            if (!file.exists () || !append) out = new ObjectOutputStream (new FileOutputStream (filename));
            else out = new AppendableObjectOutputStream (new FileOutputStream (filename, append));
            out.writeObject(obj);
            out.flush ();
        }catch (Exception e){
            e.printStackTrace ();
        }finally{
            try{
                if (out != null) out.close ();
            }catch (Exception e){
                e.printStackTrace ();
            }
        }
    }

    public static void readFromBinaryFile (String filename){
        File file = new File (filename);

        if (file.exists ()){
            ObjectInputStream ois = null;
            try{
                ois = new ObjectInputStream (new FileInputStream (filename));
                while (true){
                    String s = (String)ois.readObject ();
                    System.out.println (s);
                }
            }catch (EOFException e){

            }catch (Exception e){
                e.printStackTrace ();
            }finally{
                try{
                    if (ois != null) ois.close();
                }catch (IOException e){
                    e.printStackTrace ();
                }
            }
        }
    }

    private static class AppendableObjectOutputStream extends ObjectOutputStream {
          public AppendableObjectOutputStream(OutputStream out) throws IOException {
            super(out);
          }

          @Override
          protected void writeStreamHeader() throws IOException {}
    }
}

答案 1 :(得分:4)

  

oos = new ObjectOutputStream(new FileOutputStream(filename,true));您   编译,但是,哎呀!似乎它   继续覆盖文件。

这没有意义。 FileOutputStream是附加到现有文件的流,因此它不会覆盖该文件。检查一下。

问题是无法关闭流并重新打开以序列化多个对象。运行以下命令并比较生成的文件以进行检查。

public class XX {

 public static void writeToBinary(Object obj, String filename) throws Exception {
   ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename,true));
   oos.writeObject(obj);
   oos.close();
 }

 public static void writeToBinary2(Object obj1, Object obj2,String filename) throws Exception { 
   ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename,true));
   oos.writeObject(obj1);
   oos.writeObject(obj2);
   oos.close();
 }

 public static void main(String[] args) throws Exception {
  String s1= "hi, just trying";
  String s2= "bye bye cruel world";
  String filename = "/temp/f.dat";
  String filename2 = filename + ".2" ;
  writeToBinary(s1, filename);
  writeToBinary(s2, filename);
  writeToBinary2(s1, s2,filename2);
  ObjectInputStream fin = new ObjectInputStream(new FileInputStream(filename)); // oops... works with filename2
  Object x1 = fin.readObject();
  Object x2 = fin.readObject();
  System.out.println(x1);
  System.out.println(x2);
 }
}

答案 2 :(得分:3)

写一个帮助类。在构造函数中,它将实例化特定文件名的输出流。然后使用一些append()writeToBinary()方法,它会附加数据。在方法close()上,流上会有flush()close()次调用。

BinaryWriteHelper helper = new BinaryWriteHelper("test.dat");

helper.writeToBinary("1");
helper.writeToBinary(2);

helper.close();
BinaryWriteHelper中的

public BinaryWriteHelper(String filename) {
 this.stream = new ObjectOutputStream(new FileOutputStream(filename));
}

public close() {
  // the cleanup here
}

答案 3 :(得分:2)

尝试这种方法:

  1. 将对象写入ByteArrayOutputStream
  2. ByteArrayOutputStream的尺寸和内容附加到RandomAccessFile
  3. 要从文件加载对象,请将表示对象的字节读入ByteArrayInputStream并在此处初始化ObjectInputStream。在每个对象字节序列之前的大小字段将在这里派上用场。