'How to read and rewrite a singleton object from a file?
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;
}
}
I have the upper class which creates a single object. I want to save this object with its Lists to a file. Then when my app starts and I instantiate Storage I want it to read the file and if it is empty create a new Storage, but if its not then read the previous instance of Storage and create this new based on the old. Basically meaning that I want the contents of GroupList and MessageList to be persistent.
EDIT: because I didn't make it clear enough.
Where do I place the code needed to check and read a previous instance of this class in? I guess in the constructor, but then will my Lists also get the values of the other object? I dont know where/how to code that.
EDIT2: pasting solution.
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");
}
}
Thanks for your help! :)
Solution 1:[1]
You can add the following methods to your Storage object:
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();
}
}
You can call initialize() from your static instance method instead of calling the constructor directly.
Solution 2:[2]
It can be done by reading the object in the main method of your application and saving it again in the main method close to the shutdown point. May be I am missing something.
Solution 3:[3]
There is a good description of the Java serialization api here:
http://java.sun.com/developer/technicalArticles/Programming/serialization/
The short version is you probably need to add the following two methods to customize how your object is written. Note that these do not Override any superclass method -- just add them with these exact signatures.
Make sure your Message and Group objects are serializable as well.
Then you'll create an ObjectOuputStream and call its writeObject method to write your object to a file.
The methods to add to your Serializable class:
private void writeObject(ObjectOutputStream out) throws IOException
and
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
Solution 4:[4]
I'm assuming there's code in your real Storage class that sets member data for the Storage object. Given that, I would recommend something along the lines of:
static public Storage instance() {
if(_instance != null) {
return _instance;
}
_instance = new Storage();
if (file.exists()) {
deserialize_Storage_data_from_file();
}
return _instance;
}
Solution 5:[5]
All the above - and change those List's to be non-static too!
Solution 6:[6]
Obviously you need to store the serialized singleton in the file system, so you will need a canonical location, e.g. a config parameter for the file name.
Then, the instance accessor method effectively is in charge of marshalling/unmarshalling the persistent instance. This is the easy part. (There is a small can of worms for a robust system: you will need to insure no other process is ever writing to this file, e.g if another JVM instance comes up and uses the same singleton class. Again: the name of serialized file is a simple mechanism to address this issue.
Operationally, any changes to the instance (in mem) need to be synchronized with the persistent form, e.g. consistency requirements will demands some sort of transactional semantics. Simplest (but least efficient) is to simply flush the instance to the serialized file on every mutating action on the singleton instance, e.g. when modifying list content.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Chris |
| Solution 2 | Ashwinee K Jha |
| Solution 3 | |
| Solution 4 | Eric Hydrick |
| Solution 5 | davidfrancis |
| Solution 6 |
