<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>codify.flansite.com &#187; Serialization</title>
	<atom:link href="http://codify.flansite.com/tag/serialization/feed/" rel="self" type="application/rss+xml" />
	<link>http://codify.flansite.com</link>
	<description>Codify</description>
	<lastBuildDate>Mon, 30 Nov 2009 10:24:25 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Java Serialization &#8211; Appending Objects to an Existing File</title>
		<link>http://codify.flansite.com/2009/11/java-serialization-appending-objects-to-an-existing-file/</link>
		<comments>http://codify.flansite.com/2009/11/java-serialization-appending-objects-to-an-existing-file/#comments</comments>
		<pubDate>Tue, 24 Nov 2009 06:11:25 +0000</pubDate>
		<dc:creator>flanster</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Append]]></category>
		<category><![CDATA[Existing]]></category>
		<category><![CDATA[File]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[Serialization]]></category>

		<guid isPermaLink="false">http://codify.flansite.com/?p=206</guid>
		<description><![CDATA[The Problem
You cannot simply append objects spanning open/close pairs to a partially populated file and expect to read them later with a single pass.  Doing a series of:

open file X in append mode
write object(s) // transaction
close file

&#8230; time goes by or system reboots, etc &#8230;.

open file X in append mode
write objects(s) // transaction
close file

I&#8217;ve tried [...]]]></description>
			<content:encoded><![CDATA[<h3>The Problem</h3>
<p>You cannot simply append objects spanning open/close pairs to a partially populated file and expect to read them later with a single pass.  Doing a series of:</p>
<ol>
<li>open file X in append mode</li>
<li>write object(s) // transaction</li>
<li>close file</li>
</ol>
<p style="padding-left: 30px; ">&#8230; time goes by or system reboots, etc &#8230;.</p>
<ol>
<li>open file X in append mode</li>
<li>write objects(s) // transaction</li>
<li>close file</li>
</ol>
<p>I&#8217;ve tried this and upon reading I got this error:</p>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">java.io.StreamCorruptedException: invalid type code: AC</div>
<pre style="padding-left: 30px; ">java.io.StreamCorruptedException: invalid type code: AC</pre>
<p>This is due to the stream header appearing before each object S in the file.  It is written everytime a ObjectOutputStream is opened/created.</p>
<h3>But Wait &#8211; Why do this?</h3>
<p>It is a reasonable question.  It is likely you do not need to do this &#8211; right?  Open the file, write to it, and close it?  Doing this over and over against just seems inefficient.  Why not just write all the objects at once and be done with it.  Well, there are situations, like writing to a database log file where this might happen. You might consider rolling to a new file for each group of time-separated writes or just keep the file open.  But keeping a file open indefinitely or having many separate tiny files seems just broken somehow.  What if the file is a socket and you cannot simply open or close it anytime.</p>
<p>The key is you cannot come back to an existing file/socket and write more objects after that stream was once closed and expect to read this same stream later using a simple reverse technique.</p>
<p><em>There are techniques to work around this</em>.</p>
<h3><strong>Solution #1: Fake Multiple file in a Single Stream</strong></h3>
<p>In looking closely at the <a href="http://www.prevayler.org/">prevayler</a> code, which seems to do the same thing for command journaling, I discovered one possible technique.</p>
<p>Write your &#8220;transaction&#8221; to a ByteArrayOutputStream, then write the length and contents of this ByteArrayOutputStream to a file via the DataOutputStream.</p>
<pre style="padding-left: 30px;">ByteArrayOutputStream aos = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(aos);
DataOutputStream dos = new DataOutputStream(new FileOutputStream(outfile, true));
try
{
    os.writeObject(order);
    os.writeObject(new Date());
    os.flush();

    byte[] raw = aos.toByteArray();
    dos.writeInt(raw.length);
    dos.write(raw);
    dos.flush();
}
finally
{
    if ( os!= null ) os.close();
    if ( dos!=null ) dos.close();

}</pre>
<p>To read, reverse the process.  Read the length of the byte stream into an int, create a byte array of this length, then read that amount of data into byte array.  Once you created the ByteArrayInputStream, use it to read the transaction via ObjectInputStream.</p>
<pre style="padding-left: 30px;">DataInputStream dis = new DataInputStream(new FileInputStream(filename)); 
try{
    while ( true )
    {
        int recLen = dis.readInt();
        if ( recLen &lt;= 0 )
            break;
        byte[] raw = new byte[recLen];
        dis.read(raw);
        ByteArrayInputStream bis = new ByteArrayInputStream(raw);
<span style="white-space: pre;">	</span>ObjectInputStream is = new ObjectInputStream(bis);
<span style="white-space: pre;">	</span>int i=0;
<span style="white-space: pre;">	</span>MyClass1 obj1 = (MyClass)is.readObject();
<span style="white-space: pre;">	</span>MyClass2 obj2 = (MyClass)is.readObject();
<span style="white-space: pre;">	</span>// use or store obj1 and obj2
<span style="white-space: pre;">	</span>is.close();
    }
}
catch(EOFException e)
{
    System.out.println("Reached EOF");
}
finally
{
    if ( dis != null ) dis.close();
}</pre>
<pre><span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; line-height: 19px; white-space: normal; font-size: 13px;">You will be able to write an series of separate object-sets/transactions and then read this series later.  This has the effect of writing multiple "virtual" files sequentially into a single file.</span></pre>
<p>It will keep working regardless of changes to the underlying serialization framework.</p>
<h3>Solution #2:  Reopen and Skip</h3>
<p>Another solution involves saving the file position using:</p>
<pre style="padding-left: 30px; ">long pos = fis.getChannel().position();</pre>
<p>closing the file, reopening the file, and skipping to this position before reading the next transaction.</p>
<p>This is simply to implement.  It keeps the writing side from changing beyond the simple open/writeObject/close semantic.  This works but at the cost of performing many OS-level open/close operations and may limit performance.  The best part of this solution, however, is that it might save you from assuming you could read such files you have created.  If you have code writing logs without having tested the read side, then this code will allow you to read that data.</p>
<h3>Solution #3: Override ObjectInputStream</h3>
<p>This assumes the implementation of this class shall remain unchanged and was suggested in this thread <a href="http://forums.sun.com/thread.jspa?threadID=5383193">forums</a>.  Part of the issue is the stream header and the forum entry argues for by-passing it.  I did not try it because it seems to be a bad practice since it involves overriding protected routines.  These are protected for a reason &#8211; duh!</p>
<p>If I am missing something, or there other ways to solve this problem, I&#8217;d like to hear about them.</p>
<p>Peaceout.</p>
]]></content:encoded>
			<wfw:commentRss>http://codify.flansite.com/2009/11/java-serialization-appending-objects-to-an-existing-file/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
