[Home]CompressedSerialization

Robo Home | Changes | Preferences | AllPages

Showing revision 29
Related pages: SavingDataHowto - ReducingDataFileSize
If you ever want to store several somewhat large objects, this is probably the best way - (aside from carefully using the transient key word as was mentioned above) - feel free to insert this code into your robots if you find yourself using up your disk space for your robot:
import java.io.*;
import java.util.zip.*;

public Object readCompressedObject(String filename)
{
	try
	{
		ZipInputStream zipin = new ZipInputStream(new
		FileInputStream(getDataFile(filename + ".zip")));
		zipin.getNextEntry();
		ObjectInputStream in = new ObjectInputStream(zipin);
		Object obj = in.readObject();
		in.close();
		return obj;
	}
	catch (FileNotFoundException e)
	{
		System.out.println("File not found!");
	}
	catch (IOException e)
	{
		System.out.println("I/O Exception");
	}
	catch (ClassNotFoundException e)
	{
		System.out.println("Class not found! :-(");
		e.printStackTrace();
	}
	return null;    //could not get the object
}
 
public void writeObject(Serializable obj, String filename)
{
	try
	{
		ZipOutputStream zipout = new ZipOutputStream(new RobocodeFileOutputStream(getDataFile(filename + ".zip")));
		zipout.putNextEntry(new ZipEntry(filename));
		ObjectOutputStream out = new ObjectOutputStream(zipout);
		out.writeObject(obj);
		out.flush();
		zipout.closeEntry();
		out.close();
	}
	catch (IOException e)
	{
		System.out.println("Error writing Object:" + e);
	}
}

What this basically does is compresses your serialized objects in zip files. I can't remember exactly what degree of compression I got from doing this, but it seems like it was on the order of 1/10th the file size.

-- Kawigi


David Alves mentioned that Paul Evans' SandboxMini has two easy-to-use methods for this as well, PEWriteObject and PEReadObject.

Question department

Is anybody else but me using serialization to save data on enemy bots? I have a big problem. Since Marshmallow takes quite a while to learn what works best against a given enemy I want to train the robot before I package it and upload it. The serialized files get's packagedas they should but something goes wrong when they are to be deserialized so it always starts afresh when the packaged robot meets an enemy (for the first time after being packaged that is). I'm suspecting this could have something to with what version of some Java API objects that get serialized is used on the machine packaging and the machine running the packaged bot. Someone has an idea how to solve this? Sorry if this is confusing... The caveat is that it seems that my robot can't take advantage of saved data once packaged and running on another computer. --PEZ

What standard-java-type objects are you trying to serialize within your objects? Usually the Java documentation has a note somewhere if serialized objects under one implementation of a class will not be compatible with future releases. -- Kawigi

The objects I'm serializing are simple. Containing two doubles, two ints and one ArrayList containing even simpler objects consisting of only doubles and ints. Could it be some versioning problem with my own objects? I don't think so since I would then expect to see the failure without the packaging/unpackaging. -- PEZ

Hmmm... not sure what to say. The javadocs don't say anything about problems with serializing ArrayList objects... -- Kawigi

Well, it might be some aspect of Robocode that I have misunderstood. If "train" a development version robot and then package it and then run the packaged robot it seems unable to read the serialized objects. It doesn't matter that it is the same computer and JVM running. While using the development version there are no problems at all reading those objects. And the packaged robot has no problems reading its object files once it has reacreated them... -- PEZ


Are there examples of bots storing whole movement array's? -- Loki

What do you mean with movement arrays? Like pattern matcher data?. Between rounds all pattern matchers do this I would guess. Between matches some do it. Nibbler is one. -- PEZ

yes, i mean pattern matcher data. Between rounds i 'store' the data by using static's. Now i am looking for a way to store the data at the end of a match and retreive it at the start of a new match. I have been looking into the JavaDoc?, but find Java's IO terribly complex with al those nested streams. The code on this page shows an example and works for a simple case, but after i started saving data from my targets i now get all kinds of "inconvertible types" errors. Isn't it possible to save int's and double's? -- Loki

PEZ, is your problem with the deserialisation of data (mentioned at CompressedSerialization) solved?

Sure you can just save primitive data types. Look at SittingDuck for one way of doing this. Nibbler uses SymbolicPatternMatching and saves the string. That's one more advantage of symbolic pattern matching. Yes, I still have problems with deserialization. I haven't looked in to it, but now it is starting to become a problem again. I haven't tried to use the serial version id thingy yet. If that doesn't work I'll go for externalization instead. Should be able to save some space that way also. -- PEZ

Found the solution for my "inconvertible types" errors: I am using ObjectInput/OutputStream as in the example. When reading data from file you have to cast the object into the desired object. Example:

StringBuffer pattern = (StringBuffer)in.readObject();
When reading primitive types you have to use the appropriate methods from the ObjectInputStream? class. Example:
int historyCounter = in.readInt();
-- Loki

New question: I found in the Robocode version info that the quota for files is 200k (as for robocode version 1.06). How can you prevent running out of 'disk space' -- Loki

The only way must be to check if what you want to write fits in the space left and then you have to either save less or delete something from your directory. Check TheArtOfWar code, it handles this situation. -- PEZ


Did any one try this with jdk1.4.2 beta. I have some problems to save or load data. I tried Marshmallow as well it also fails. Any ideas? --SSO?

What problems do you encounter? I use jdk1.4.1 b.t.w. --Loki

In what way does Marshmallow fail? -- PEZ

Mainly it's security problem. My bot has the same problem. Here is the exception

pez.Marshmallow 1.5.3: Exception: java.security.AccessControlException?: Preventing pez.Marshmallow 1.5.3 from access: (java.io.FilePermission? E:\java\robocode\robots\pez read): You may only read files in your own root package directory. java.security.AccessControlException?: Preventing pez.Marshmallow 1.5.3 from access: (java.io.FilePermission? E:\java\robocode\robots\pez read): You may only read files in your own root package directory.

    at robocode.security.RobocodeSecurityManager?.checkPermission(RobocodeSecurityManager?.java:314)
    at java.lang.SecurityManager?.checkRead(SecurityManager?.java:863)
    at java.io.File.exists(File.java:678)
    at java.io.Win32FileSystem?.canonicalize(Win32FileSystem?.java:358)
    at java.io.File.getCanonicalPath?(File.java:513)
    at java.io.File.getCanonicalFile?(File.java:534)
    at robocode.peer.robot.RobotFileSystemManager?.getReadableDirectory?(RobotFileSystemManager?.java:110)
    at robocode.security.RobocodeSecurityManager?.checkPermission(RobocodeSecurityManager?.java:299)
    at java.lang.SecurityManager?.checkRead(SecurityManager?.java:863)
    at java.io.File.exists(File.java:678)
    at java.io.Win32FileSystem?.canonicalize(Win32FileSystem?.java:358)
    at java.io.File.getCanonicalPath?(File.java:513)
    at java.io.File.getCanonicalFile?(File.java:534)
    at robocode.peer.robot.RobotFileSystemManager?.getWritableDirectory?(RobotFileSystemManager?.java:125)
    at robocode.AdvancedRobot.getDataFile?(AdvancedRobot.java:363)
    at pez.Marshmallow.writeObject(Unknown Source)
    at pez.Marshmallow.saveStatistics(Unknown Source)
    at pez.Marshmallow.onRobotDeath?(Unknown Source)
    at robocode.peer.robot.EventManager?.onRobotDeath?(EventManager?.java:598)
    at robocode.peer.robot.EventManager?.processEvents(EventManager?.java:742)
    at robocode.peer.RobotPeer?.tick(RobotPeer?.java:1024)
    at robocode.AdvancedRobot.execute(AdvancedRobot.java:186)
    at pez.Marshmallow.run(Unknown Source)
    at robocode.peer.RobotPeer?.run(RobotPeer?.java:616)
    at java.lang.Thread.run(Thread.java:534)

--SSO?

And does SittingDuck have the same problem? -- PEZ

NO! --SSO?

Strange, I was almost sure it should... -- PEZ

Do you use getDataFile?() or whatever? -- Kawigi

I had the same problem. Solved it by

while (!dataIsLoaded?) {

    try {
        tryToReadData?;
        dataIsLoaded? = true;
    } catch (AnyException? e) {}
}

this looks like something that should never work, but it does. about every 10th try to read anthing, the exception occurs. randomly. so i just try to read the file over and over again until robocode gives up, and i get the file. same for saving. -HoD

Wait, I'm confused; how come it lets you catch an AccessControlException? and allows the bot to keep going? When I was testing out the effects of referencing GL classes on regular Robocode, even if I caught the AccessControlException?, Robocode would still disable my robot and kill its thread.

Also, does that zipping code write the .zip header with the file, or does it just write the zip data bare? Because if it is, you're saving a zip header for nothing. I mean it could only be a few bytes per file, but still... -- Vuen

Such is true. You can also be classy and make a zip file with a file in it for each enemy if you wanted. Or you can go SandboxMini's route (and presumably SandboxDT's) and use a GZip compression thingy. (I don't know if that changes the header stuff). Or you could be REALLY like Paul Evans and make your own complete compression scheme. -- Kawigi

I am suffering with the java.security.AccessControlException? problem since upgrading to Java version 1.4.2. I have observed the following...

My present solution to work around the problem is to do all file reads in round 1, storing the data in statics - catching the exception and re-reading if necessary. At worst you will loose round 1 because of being disabled. For any other file I/O perform at then end of the round - retyring if the output is important.

-- Paul Evans

I'm suffering the same problem... I suppose it's a problem with the way java 1.4.2 handles the File object I suppose that the problem stay in this row, where robocode try to read the file directory.

File dir = (new File(robotPeer.getRobotClassManager().getRobotClassLoader().getClassDirectory(), robotPeer.getRobotClassManager().getClassNameManager().getShortClassName() + ".data")).getCanonicalFile();

This piece of code stay in the file robocode.peer.robot.RobotFileSystemManager?: I suppose that getClassDirectory?() misbehave in same way. Update: I tryed installing 1.4.2_01 but still have the problem -- Simonech


Robo Home | Changes | Preferences | AllPages
Edit revision 29 of this page | View other revisions | View current revision
Edited September 26, 2003 16:44 EST by Simonech (diff)
Search: