2011-01-10 7 views
1

Supose у вас есть следующий метод:добавляющих объектов в двоичный файл

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:

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

Вы скомпилировать, но, возгласы !, кажется, что он продолжает переопределяя файл.

Ну, проблемы начинаются. После поиска в google вы читаете, что вы должны использовать ObjectOutputStream SAME, чтобы добавить объекты в один и тот же файл. Вы хотите иметь функцию, которая каждый раз, когда вы ее вызываете, добавляет объект. То есть :

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

Но, как я уже говорил, вы должны использовать один и тот же ObjectOutputStream.

Решение 1:

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

Это очень некрасиво, потому что я хочу, чтобы скрыть использование потоков.

Есть ли другое решение?

EDIT: метод является статическим. Он находится внутри класса утилиты, где все методы являются статическими.

EDIT2: SOLVED! Appending to an ObjectOutputStream. См. Принятый ответ на мой вопрос. Спасибо.

ответ

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 {} 
    } 
} 
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 
} 
+0

Метод письма является статическим. Он находится внутри класса утилиты, где все методы являются статическими. –

+0

просто используйте экземпляр класса вместо статических методов. Static здесь не так, потому что это транзакционная ситуация. –

4

OOS = новый ObjectOutputStream (новый FileOutputStream (имя файла, правда)); Вы скомпилируйте, но, крик !, кажется, что он продолжает отменять файл.

Это не имеет смысла. 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); 
} 
} 
+0

Это то, что я сказал, этот код будет работать только с filename2. –

2

Попробуйте этот подход:

  1. Написать объект в ByteArrayOutputStream.
  2. Приложите размер и содержимое ByteArrayOutputStream к RandomAccessFile.
  3. Чтобы загрузить объект из файла, прочитайте байты, представляющие объект, в ByteArrayInputStream и выполните инициализацию ObjectInputStream. Поле размера, которое было добавлено к каждой последовательности байтов объектов, пригодится здесь.
+0

Проблема в том, что вы добавляете дополнительные байты в исходный файл. –

Смежные вопросы