2011-12-02 59 views
0
public class Storage implements Serializable{ 

    /** 
    * 
    */ 
    private static final long serialVersionUID = 1L; 
    public static List<Message> MessageList = Collections.synchronizedList(new ArrayList<Message>()); //Fail safe if multiple threads modify them. 
    public static List<Group> GroupList = Collections.synchronizedList(new ArrayList<Group>()); 

    protected Storage() { 
     super(); 
    } 

    static private Storage _instance = null; 

    //initialized: Storage.instance(); 
    static public Storage instance() { 
     if(_instance == null) { 
      _instance = new Storage(); 
     } 
    return _instance; 
    } 



} 

我有创建单个对象的上层类。我想将这个对象的列表保存到一个文件中。然后当我的应用程序启动时,我实例化存储我希望它读取文件,如果它是空创建一个新的存储,但如果它不然后读取以前的存储实例,并创建基于旧的这个新的。基本上意味着我希望GroupList和MessageList的内容持久。如何从文件中读取和重写单例对象?

编辑:因为我没有说清楚。

我在哪里放置检查和读取此类的前一个实例所需的代码?我想在构造函数中,但是然后我的列表也会得到另一个对象的值?我不知道在哪里/如何编码。

EDIT2:粘贴解决方案。

public class Storage implements Serializable{ 

    /** 
    * 
    */ 
    private static final long serialVersionUID = 1L; 
    public static List<Message> MessageList = Collections.synchronizedList(new ArrayList<Message>()); //Fail safe if multiple threads modify them. 
    public static List<Group> GroupList = Collections.synchronizedList(new ArrayList<Group>()); 

    protected Storage() { 
     super(); 
    } 

    static private Storage _instance = null; 

    //initialized: Storage.instance(); 
    public static synchronized Storage instance(){ 
     initialize(); 
     if(_instance == null) { 
      _instance = new Storage(); 
     } 
     return _instance; 
    } 

    public static synchronized void persist(){ 
     FileOutputStream fos = null; 
     ObjectOutputStream out = null; 
     try{ 
      fos = new FileOutputStream("Storage.txt"); 
      out = new ObjectOutputStream(fos); 
      out.writeObject(instance()); 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     }finally{ 
      try { 
       out.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 



    protected static synchronized void initialize(){ 
     FileInputStream fis = null; 
     ObjectInputStream in = null; 
     try{ 
      fis = new FileInputStream("Storage.txt"); 
      in = new ObjectInputStream(fis); 
      _instance = (Storage)in.readObject(); 
     } catch (ClassNotFoundException e) { 
      e.printStackTrace(); 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } catch (OptionalDataException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     }finally{ 
      try { 
       in.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    public static synchronized void addElement(Message message){ 
     if(!MessageList.contains(message)){ 
      MessageList.add(message); 
      persist(); 
      Log.i("STORAGE-addElement", "Added: " + message); 
     } 
    } 

    public static synchronized void addElement(Group group){ 
     if(!GroupList.contains(group)){ 
      GroupList.add(group); 
      persist(); 
      Log.i("STORAGE-addElement", "Added: " + group); 
     } 
    } 

    public static synchronized void removeElement(Message message){ 
     if(!MessageList.contains(message)){ 
      MessageList.remove(message); 
      persist(); 
      Log.i("STORAGE-removeElement", "Removed: " + message); 
     } 
    } 

    public static synchronized void removeElement(Group group){ 
     if(!GroupList.contains(group)){ 
      GroupList.remove(group); 
      persist(); 
      Log.i("STORAGE-removeElement", "Removed: " + group); 
     } 
    } 

    public static synchronized void wipeAll(){ 
     MessageList.clear(); 
     GroupList.clear(); 
     persist(); 
     Log.i("STORAGE-wipeAll", "Wiped all data"); 
    } 

} 

感谢您的帮助! :)

+0

当我不得不做这种事情时,我使用了dom4j库,它允许您非常容易地将对象保存到xml文件。现在可能有更好的办法 –

+2

这个过程的哪一部分是你遇到的问题? – Shaun

+0

@Shaun编辑。 – Miky

回答

2

您可以将以下方法添加到Storage对象:

public void persist() throws IOException{ 

    FileOutputStream fos = null; 
    ObjectOutputStream out = null; 
    try{ 
    fos = new FileOutputStream(FILE_NAME); //assumes filename is a constant you've defined 
    out = new ObjectOutputStream(fos); 
    out.writeObject(time); 
    }finally{ 
    out.close(); 
    } 
} 



protected static void initialize() throws IOException{ 
    FileInputStream fis = null; 
    ObjectInputStream in = null; 
    try{ 
    fis = new FileInputStream(FILE_NAME); 
    in = new ObjectInputStream(fis); 
    instance = (PersistentTime)in.readObject(); 
    }finally{ 
    in.close(); 
    } 
} 

您可以从静态instance方法调用initialize()而不是直接调用构造函数。

+0

一个很好的开始恕我直言 - 你太善良的操作系统,克里斯8 =} – davidfrancis

+0

你做任何初始化静态的好理由? – havexz

+0

,所以你可以从一个静态的上下文(即从实例方法)调用它。 – Chris

2

它可以通过读取应用程序的主要方法中的对象并在靠近关闭点的主方法中再次保存它来完成。可能是我错过了一些东西。

1

我假设您的真实存储类中存在用于设置存储对象成员数据的代码。鉴于此,我建议一些沿行:

static public Storage instance() { 
    if(_instance != null) { 
     return _instance; 
    } 

    _instance = new Storage(); 

    if (file.exists()) { 
     deserialize_Storage_data_from_file(); 
    } 

    return _instance; 
} 
1

显然,你需要存储在文件系统的系列化单,所以你需要一个规范位置,例如文件名的配置参数。然后,实例访问器方法有效地负责编组/解组持久实例。这是简单的部分。 (对于一个健壮的系统,有一小部分蠕虫:你需要确保没有其他进程正在写入这个文件,例如,如果另一个JVM实例出现并且使用相同的单例类。再一次:序列化文件的名称是一个简单的机制来解决这个问题

在操作上,对实例(在mem中)的任何更改都需要与持久化表单进行同步,例如一致性需求将需要某种事务性语义。最简单(但效率最低)是只需将实例刷新到单例实例上的每个变更操作上的序列化文件,例如,修改列表内容时。

2

还有这里的Java序列化API的一个很好的说明:

http://java.sun.com/developer/technicalArticles/Programming/serialization/

简短的版本是,你可能需要以下两个方法添加到自定义对象是如何写的。请注意,这些不会覆盖任何超类方法 - 只需使用这些确切的签名来添加它们即可。

确保您的消息和组对象也是可序列化的。

然后,您将创建一个ObjectOuputStream并调用其writeObject方法将对象写入文件。

的方法添加到您的Serializable类:

private void writeObject(ObjectOutputStream out) throws IOException 

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException 
1

上述所有 - 和改变这些列表的是非静态的呢!

+0

它们是静态还是不静态?需要更多资源还是? – Miky

+0

我不相信静力学会坚持与主要对象 - 你有没有找到其他? – davidfrancis