Slick Forums

Discuss the Slick 2D Library
It is currently Sat May 25, 2013 12:14 am

All times are UTC




Post new topic Reply to topic  [ 4 posts ] 
Author Message
PostPosted: Wed May 05, 2010 4:24 am 
Offline

Joined: Tue Mar 30, 2010 4:49 am
Posts: 2
When noodling on my project of choice, I found that I wanted to read a configuration file lying in my main game folder. So I made this simple, probably buggy, class to handle the parsing duties for me.

It reads text streams that look like this:
config.cfg
Code:
resolution=800x600
fullscreen=true
multisampling=8


And allows them to be accessed like a Map (the class extends HashMap<String,String>). To get one of the configuration properties, you'd do something like this;
Code:
//Make a ConfigFile
ConfigFile configFile = new ConfigFile("config.cfg");

//Returns the string "800x600"
configFile.get("resolution");

//Returns the string "true"
configFile.get("fullscreen");


I've also added a couple convenience methods that will parse booleans and base-10 integers for you.
Code:
//Returns true
configFile.getBoolean("fullscreen");

//Returns 8
configFile.getInteger("multisampling");


Should you alter the entries in the map, and desire to return it to it's former pristine state, you can call reset() to return it to the state it was in just after construction, or you can call repopulate() in order to add the entries from the config file to the map again, overriding any existing values.

Without further ado, the code.
Code:
import java.io.InputStream;
import java.util.HashMap;
import java.util.Scanner;

/**
* A set of configuration properties derived from a file and accessible as a
* map.
*
* @author Cameron Seebach
*
*/
public class ConfigFile extends HashMap<String, String> {
   /**
    * The serialVersionUID of the ConfigFile class.
    *
    * @see java.io.Serializable
    */
   private static final long serialVersionUID = -7456741886840905637L;

   /**
    * The Scanner through which the config file is read.
    */
   private final Scanner scanner;
   
   public ConfigFile(String fileName) {
      this(getStreamFor(fileName));
   }

   /**
    * Creates a ConfigFile from the given input stream.
    *
    * @param input
    *            the input stream to read for configuration information
    */
   public ConfigFile(InputStream input) {
      this(new Scanner(input));
   }

   /**
    * Creates a ConfigFile from the given Scanner.
    *
    * @param input
    *            the Scanner to read for configuration information
    */
   private ConfigFile(Scanner input) {
      scanner = input;
      repopulate();
   }

   private static InputStream getStreamFor(String fileName){
      return Thread.currentThread().getContextClassLoader()
      .getResourceAsStream(fileName);
   }
   
   /**
    * Reset this ConfigFile to the way it was when you created it.
    */
   public void reset(){
      clear();
      repopulate();
   }
   
   /**
    * Puts all the configuration properties and values from the file into the
    * hashmap.
    */
   public void repopulate() {
      scanner.reset();
      while (scanner.hasNextLine()) {
         String nextLine = scanner.nextLine();
         if (nextLine.startsWith("//"))
            continue;
         String[] splitResults = nextLine.split(" = ");
         if (splitResults.length != 2)
            continue;
         String propertyName = splitResults[0].trim();
         String propertyValue = splitResults[1].trim();

         put(propertyName, propertyValue);
      }
   }

   /**
    * Returns true if the given property currently exists and is associated
    * with a boolean value in this ConfigProperties.
    *
    * @param propertyName
    *            the name of the property to test for
    * @return true if the given property exists and is associated with a
    *         boolean value. otherwise, false
    */
   public boolean containsBoolean(String propertyName) {
      return getBoolean(propertyName) != null;
   }

   /**
    * @param propertyName
    * @return
    */
   public Boolean getBoolean(String propertyName) {
      String result = get(propertyName);
      if (result != null)
         return parseBoolean(result);
      return null;
   }

   /**
    * @param bool
    * @return
    */
   private Boolean parseBoolean(String bool) {
      if (bool.equalsIgnoreCase("true")) {
         return true;
      } else if (bool.equalsIgnoreCase("false"))
         return false;
      return null;
   }

   public boolean containsInteger(String propertyName) {
      return getInteger(propertyName) != null;
   }

   /**
    * @param propertyName
    * @return
    */
   public Integer getInteger(String propertyName) {
      String result = get(propertyName);
      if (result != null)
         return parseInteger(result);
      return null;
   }

   /**
    * @param result
    * @return
    */
   private Integer parseInteger(String result) {
      try {
         return Integer.valueOf(result);
      } catch (NumberFormatException e) {
         return null;
      }
   }
}


I'm afraid I have still managed to make a mess of things. But if I try to make it perfect, it will never see the light of day! Hope someone finds this useful.


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 05, 2010 4:38 am 
Offline

Joined: Sat Oct 04, 2008 3:58 am
Posts: 99
I ended up using Simple for my game. I was using it for XML parsing anyway, and it works great for this as well. Simply mock up a class for config (Which most of you probably have anyway), add a few tags, and viola! Instant XML. Loading create an instance of the object you saved with.

The biggest issue I see with your solution right now is: if (splitResults.length != 2)

It's probably safe to assume the config var will never have an = in it (Though document this restriction somewhere). But the value should simply be everything behind the first =.

If you're saving stuff like high scores, character names, serialized data, etc. there are many chances for an = to slip in and break the value.


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 05, 2010 5:52 am 
Offline
Game Developer
User avatar

Joined: Wed Feb 17, 2010 12:24 am
Posts: 594
I use JavaINI. It's really simple and fast to get going.
http://ini4j.sourceforge.net/

My config looks like this:

Code:
// PowerEngine Settings 

[GENERAL]
theme = twl_default
screenshotformat = .png
showintro = false

[VIDEO]
width = 1024
height = 768
fullscreen = false
maxfps = 240
vsync = false
multisampling = 0

[SOUND]
musicvolume = 7
soundvolume = 6

[DEBUG]
logdebugmessages = true
showfps = true

[ADVANCED]
renderer = 0
linestriprenderer = 0



Top
 Profile  
 
 Post subject:
PostPosted: Wed May 05, 2010 6:28 am 
Offline
Slick Zombie

Joined: Wed Apr 02, 2008 1:32 pm
Posts: 1315
Location: Italy
you can always use properties files: http://java.sun.com/javase/6/docs/api/j ... rties.html

p.s.: everyone have a different way to do that :D

_________________
Blog | Last game Gravity Duck tribute | In progress Gravity Duck tribute


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group