R
Roedy Green
Ordinary java.util.Properties have two drawbacks:
1. spaces must be awkwardly encoded as "\ "
2. there is no provision for a value to have multiple values.
Here is a simple replacement for the Properties class that gets around
that.
It is a little clumsy. Here is the code to do with as you please:
package com.mindprod.replicator;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.regex.Pattern;
/**
* This class is similar to java.util.Properties.
* The properties file has a similar key=value format.
* However, spaces in the values are not coded as "\ ", just as plain
" ".
* Values can be a tuple separated by commas.
* Multiple values are returned by get as a String[].
* Single values are returned as String.
* There is no support for extended chars such as \n.
* There is no support for \ as a continuation character.
* Comment lines begin with #.
* Blank lines are ignored.
* The file must end with a separator.
* All values are trimmed of leading and trailing spaces.
*
* It is basically just a Hashtable with a load method.
*
* @author Roedy Green
* @version 1.0
* @since 2003-08-03
*/
public class MultiProperties extends Hashtable
{
/**
* true if you want the debugging harness code.
*/
private static final boolean DEBUG = true;
/**
* Constructs a new, empty hashtable with the specified initial
* capacity and the specified load factor.
* See http://mindprod.com/jgloss/hashtable.html for a full
description of
* what the initialCapacity and loadFactors mean.
*
* @param initialCapacity the initial capacity of the
hashtable.
* @param loadFactor the load factor of the hashtable.
* @exception IllegalArgumentException if the initial capacity is
less
* than zero, or if the load factor is nonpositive.
*/
public MultiProperties ( int initialCapacity, float loadFactor )
{
super( initialCapacity, loadFactor );
}
/**
* Load the properties hasthtable from a text file of key=value
pairs.
*
* @param in where to load the textual key=value pairs from.
*/
public void load ( InputStream in ) throws IOException
{
BufferedReader br = new BufferedReader( new InputStreamReader(
in ) );
while ( true )
{
String line = br.readLine();
if ( line == null )
{
/* eof */
break;
}
if ( line.startsWith( "#" ) )
{
/* ignore comments */
continue;
}
line = line.trim();
if ( line.length() == 0 )
{
/* ignore blank lines */
continue;
}
// split line into key and value
String[] keyValue = keyValueSplitter.split( line );
switch ( keyValue.length )
{
case 1:
{
// key= nothing
String key = keyValue[0].trim();
if ( key.length() == 0 )
{
throw new IllegalArgumentException( "malformed
key=value : " + line );
}
this.put( key, "" );
}
break;
case 2:
{
// key=value
String key = keyValue[0].trim();
if ( key.length() == 0 )
{
throw new IllegalArgumentException( "malformed
key=value : " + line );
}
// Split value into subfields
String[] values = subFieldSplitter.split(
keyValue[1].trim() );
switch ( values.length )
{
case 0:
// empty value
this.put( key, "" );
break;
case 1:
// one value
this.put( key, values[0].trim() );
break;
default:
// multiple values
for ( int i=0; i<values.length; i++ )
{
values = values.trim();
}
this.put ( key, values );
break;
}
}
break;
default:
throw new IllegalArgumentException( "malformed
key=value : " + line );
}
} // end while
br.close();
} // end load
// Pattern to split line into key and value at the =
private static Pattern keyValueSplitter = Pattern.compile ( "=" );
// Pattern to split into words separated by commas. two commas in a
row gives an empty field
private static Pattern subFieldSplitter = Pattern.compile ( "," );
/**
* test harness
*
* @param args not used
*/
public static void main ( String[] args )
{
if ( DEBUG )
{
MultiProperties m = new MultiProperties ( 100, .75f );
try
{
m.load( new FileInputStream ( "replicator.properties" ) );
}
catch ( IOException e )
{
e.printStackTrace();
System.exit( 1 );
}
for ( Enumeration e = m.keys(); e.hasMoreElements(); )
{
String key = (String) e.nextElement();
Object value = m.get( key );
System.out.println( key + " =");
if ( value instanceof String[] )
{
String[] values = (String[]) value;
for ( int i=0; i<values.length; i++ )
{
System.out.println ( values );
}
}
else
{
System.out.println ( (String) value );
}
} // end for
} // end if DEBUG
} // end main
} // end MultiProperties
1. spaces must be awkwardly encoded as "\ "
2. there is no provision for a value to have multiple values.
Here is a simple replacement for the Properties class that gets around
that.
It is a little clumsy. Here is the code to do with as you please:
package com.mindprod.replicator;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.regex.Pattern;
/**
* This class is similar to java.util.Properties.
* The properties file has a similar key=value format.
* However, spaces in the values are not coded as "\ ", just as plain
" ".
* Values can be a tuple separated by commas.
* Multiple values are returned by get as a String[].
* Single values are returned as String.
* There is no support for extended chars such as \n.
* There is no support for \ as a continuation character.
* Comment lines begin with #.
* Blank lines are ignored.
* The file must end with a separator.
* All values are trimmed of leading and trailing spaces.
*
* It is basically just a Hashtable with a load method.
*
* @author Roedy Green
* @version 1.0
* @since 2003-08-03
*/
public class MultiProperties extends Hashtable
{
/**
* true if you want the debugging harness code.
*/
private static final boolean DEBUG = true;
/**
* Constructs a new, empty hashtable with the specified initial
* capacity and the specified load factor.
* See http://mindprod.com/jgloss/hashtable.html for a full
description of
* what the initialCapacity and loadFactors mean.
*
* @param initialCapacity the initial capacity of the
hashtable.
* @param loadFactor the load factor of the hashtable.
* @exception IllegalArgumentException if the initial capacity is
less
* than zero, or if the load factor is nonpositive.
*/
public MultiProperties ( int initialCapacity, float loadFactor )
{
super( initialCapacity, loadFactor );
}
/**
* Load the properties hasthtable from a text file of key=value
pairs.
*
* @param in where to load the textual key=value pairs from.
*/
public void load ( InputStream in ) throws IOException
{
BufferedReader br = new BufferedReader( new InputStreamReader(
in ) );
while ( true )
{
String line = br.readLine();
if ( line == null )
{
/* eof */
break;
}
if ( line.startsWith( "#" ) )
{
/* ignore comments */
continue;
}
line = line.trim();
if ( line.length() == 0 )
{
/* ignore blank lines */
continue;
}
// split line into key and value
String[] keyValue = keyValueSplitter.split( line );
switch ( keyValue.length )
{
case 1:
{
// key= nothing
String key = keyValue[0].trim();
if ( key.length() == 0 )
{
throw new IllegalArgumentException( "malformed
key=value : " + line );
}
this.put( key, "" );
}
break;
case 2:
{
// key=value
String key = keyValue[0].trim();
if ( key.length() == 0 )
{
throw new IllegalArgumentException( "malformed
key=value : " + line );
}
// Split value into subfields
String[] values = subFieldSplitter.split(
keyValue[1].trim() );
switch ( values.length )
{
case 0:
// empty value
this.put( key, "" );
break;
case 1:
// one value
this.put( key, values[0].trim() );
break;
default:
// multiple values
for ( int i=0; i<values.length; i++ )
{
values = values.trim();
}
this.put ( key, values );
break;
}
}
break;
default:
throw new IllegalArgumentException( "malformed
key=value : " + line );
}
} // end while
br.close();
} // end load
// Pattern to split line into key and value at the =
private static Pattern keyValueSplitter = Pattern.compile ( "=" );
// Pattern to split into words separated by commas. two commas in a
row gives an empty field
private static Pattern subFieldSplitter = Pattern.compile ( "," );
/**
* test harness
*
* @param args not used
*/
public static void main ( String[] args )
{
if ( DEBUG )
{
MultiProperties m = new MultiProperties ( 100, .75f );
try
{
m.load( new FileInputStream ( "replicator.properties" ) );
}
catch ( IOException e )
{
e.printStackTrace();
System.exit( 1 );
}
for ( Enumeration e = m.keys(); e.hasMoreElements(); )
{
String key = (String) e.nextElement();
Object value = m.get( key );
System.out.println( key + " =");
if ( value instanceof String[] )
{
String[] values = (String[]) value;
for ( int i=0; i<values.length; i++ )
{
System.out.println ( values );
}
}
else
{
System.out.println ( (String) value );
}
} // end for
} // end if DEBUG
} // end main
} // end MultiProperties