System.out.println("Hello brave souls!");
I have a few questions about Object Serialization. I am working on a new version of my math game, and forgot to have it save the game mode on the last three sessions. The records are being saved via object serialization, which leads me here. What I want to know is:
1.) Does object serialization somehow keep hold of the time at which the objects were saved to the file?
2.) In changing ANY of the n objects in the file, do you have to load the one you want to change into memory (via cycling through the objects with a loop), change it, and then rewrite EVERY LAST FREAKING OBJECT back to the file? //seems tedious
Serialization serializes an entire object graph. If you are saving a game, you will probably want to call ObjectOutputStream.writeObject(myGame), which will write the entire game object and all non-transient properties it references, recursively.
To change it, load the game into memory using an ObjectInputStream, change a value, and write it back out.
You might also want to chain a GZIPInputStream and GZIPOutputStream if you are dealing with large amounts of data, it can shrink serialized size a good bit.
If you are dealing with really large objects, an embedded database might be a better option, since you can change a single field without loading the whole thing into RAM.
Lastly, if you want to update the timestamp of an object when it's serialized, implement the writeObject method in the Serializable pseudo-interface. Update your timestamp, then call defaultWriteObject on the supplied ObjectOutputStream. This will give you 'last persisted' behavior.
private void writeObject(java.io.ObjectOutputStream out) throws IOException
1.) Does object serialization somehow keep hold of the time at which the objects were saved to the file?
No. It saves the object and only the object, plus whatever it needs to reconstitute it, such as its class name.
2.) In changing ANY of the n objects in the file
You can't change any of the N objects in the file. You have to reconstitute the file as objects, change the object(s), and reserialize.
// seems tedious
It is tedious. Nobody said it wouldn't be tedious. You are using it as a database. It isn't. It is a serialization, which also implies that it is a stream. Exactly the same applies to a text file.
Related
Say I have a large file with many objects already serialized (this is the easy part). I need to be able to have random access to the objects in the file when I go to deserialize. The only way I can think to do this would be to somehow store the file pointer to each object.
Basically I will end up with a large file of serialized objects and don't want to deserialize the entire file when I go to retrieve just one object.
Can anyone point me in the right direction on this one?
You can't. Serialization is called serialization for a reason. It is serial. Random access into a stream of objects will not work, for several reasons including the stream header, object handles, ...
Straight serialization will never be the solution you want.
The serial portion of the name means that the objects are written linearly to the ObjectOutputStream.
The serialization format is well known,
here is a link to the java 6 serialization format.
You have several options:
Unserialize the entire file and go from there.
Write code to read the serialized file and generate an index.
Maybe even store the index in a file for future use.
Abandon serialization to a file and store the objects in a database.
Writing Java objects or a List into a text file is ok. But I want to know how I can update or rewrite a object which was written previously without writing objects again. For example, let s assume there is a java.util.List has a set of Objects. and then that list is written to a text file. Then later that file will be read again and get all objects from list and then change one object's value at run time by a java application. Then I don't need to write entire list back to the text file. Instead only the updated object in the list is required to be rewritten or updated in the text file without rewriting the whole list again. Any suggestion, or helpful source with sample codes please.
Take a look at RandomAccessFile. This will let you seek to the place in the file you want, and only update the part that you want to update.
Also take a look at this question on stackoverflow.
Without some fairly complex logic, you won't usually be able to update an object without rewriting the entire file. For example, if one of the objects on your list contains a string "shortstring", and you need to update it with string "muchmuchlongerstring", there will be no space in the file for the longer string without rewriting all the following content in the file.
If you want to persist large object trees to a file and still have the ability to update them, your code will be less buggy and life will be simplified by using one of the many file-based DBs out there, like:
SQLite (see Java and SQLite)
Derby
H2 (disk-based tables)
When continuously writing/reading sets of data through a socket, how do you recognize the end of 1 set, the start of the next set, and if the entire set is even in the stream for retrieval yet, and not just a piece of it?
To make things simple let's say I'm sending JSON strings through the socket. How do I know if the whole object is there, and get that object from start to finish so I can correctly read it? Keep in mind there may be more objects behind this one.
That depends. If you use an ObjectOutputStream then Java takes care of this for you. Obviously this is Java specific and requires you to have a ObjectInputStream on the other side. It also expects that you send serializable objects to the other side. String however is a serializable object, and I would in general expect any data structure to be serializable.
Otherwise you will have to think of some kind of container format yourself. Nowadays it is also pretty common to use XML structures to serialize the data into. If you go to an even higher level you get to the point of using web-services.
If I have a property of an object which is a large String (say the contents of a file ~ 50KB to 1 MB, maybe larger), what is the practice around declaring such a property in a POJO? All I need to do is to be able to set a value from one layer of my application and transfer it to another without making the object itself "heavy".
I was considering if it makes sense to associate an InputStream or OutputStream to get / set the value, rather than reference the String itself - which means when I attempt to read the value of the contents, I read it as a stream of bytes, rather than a whole huge string loaded into memory... thoughts?
What you're describing depends largely on your anticipated use of the data. If you're delivering the contents in raw form, then there may be more efficient ways to manage it.
For example, if your app has a web interface, your app may just provide a URL for a web server to stream the contents to the requester. If it's a CLI-based app, you may be able to get away with a simple file copy. If your app is processing the file, however, then perhaps your POJO could retain only the results of that processing rather than the raw data itself.
If you wish to provide a general pattern along the lines of using POJO's with references to external streams, I would suggest storing in your POJO something akin to a URI that tells where to find the stream (like a row ID in a database or a filename or a URI) rather than storing an instance of the stream itself. In doing so, you'll reduce the number of open file handles, prevent potential concurrency issues, and will be able to serialize those objects locally if needed without having to duplicate the raw data persisted elsewhere.
You could have an object that supplies a stream or an iterator every time you access it. Note that the content has to live on some storage, like a file. I.e your object will store a pointer (e.g. a file path) to the storage and every time someone access it, you open a stream or create an iterator and let that party read. Note also that in order to save on memory, whoever consumes it has to make sure not to store the whole content in memory.
However, 50KB or 1MB is really tiny. Unless you have like gigabytes (or maybe hundred megabytes), I wouldn't try to do something like that.
Also, even if you have large data, it's often simpler to just use files or whatever storage you'll use.
tl;dr: Just use String.
Or is there any way to cast a generic object(that originally was a 2Darray) to a 2d Array without knowing its size?
I have a program where the user enter data and that data is submitted into a 2D array that varies in size depending on how much the user entered. I saved the array as an object to file using what I learned from this tutorial.
http://beginwithjava.blogspot.com/2011/04/java-file-save-and-file-load-objects.html
([to save] open file, open object stream, write objects, close)
([to restore] Open a file. Open an object stream from the file. Read objects to stream.
Cast objects, Close the stream and file.)
However, since I can't know how large the 2d array will be, I can't figure out how to cast the object back into a 2dArray when it comes time to restore.
There is no way to know the size ahead of reading, so the most common solution is to save the size before saving the data. The reader than reads the size, allocates enough memory, and procedes with reading the data the regular way.
The other less common way is to save markers in the file to indicate where each row of data ends. In a way, this is similar to null-terminating your strings in C, where the length of the string is not stored explicitly, but must be recomputed each time. This method has a disadvantage of not allowing pre-allocation. In other words, you would either need to allocate enough memory to accommodate the data of any legal size, or re-allocate dynamically as you go.
javas ArrayList automatically grows as needed, and is usefull if you are in the unlucky situation that the no of elements are unknown.
after the file is read you can convert these arraylists to an array.
but much better is to store the size at the beginning of the file.