Task: Read a configuration file





Java: import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ConfigReader {
    private static final Pattern             LINE_PATTERN = Pattern.compile( "([^ =]+)[ =]?(.*)" );
    private static final Map<String, Object> DEFAULTS     = new HashMap<String, Object>() {{
        put( "needspeeling", false );
        put( "seedsremoved", false );
    }};

    public static void main( final String[] args ) {
        System.out.println( parseFile( args[ 0 ] ) );
    }

    public static Map<String, Object> parseFile( final String fileName ) {
        final Map<String, Object> result = new HashMap<String, Object>( DEFAULTS );
         BufferedReader      reader = null;

        try {
            reader = new BufferedReader( new FileReader( fileName ) );
            for ( String line; null != ( line = reader.readLine() );  ) {
                parseLine( line, result );
            }
        } catch ( final IOException x ) {
            throw new RuntimeException( "Oops: " + x, x );
        } finally {
            if ( null != reader ) try {
                reader.close();
            } catch ( final IOException x2 ) {
                System.err.println( "Could not close " + fileName + " - " + x2 );
            }
        }

        return result;
    }

    private static void parseLine( final String line, final Map<String, Object> map ) {
        if ( "".equals( line.trim() ) || line.startsWith( "#" ) || line.startsWith( ";" ) )
            return;

        final Matcher matcher = LINE_PATTERN.matcher( line );

        if ( ! matcher.matches() ) {
            System.err.println( "Bad config line: " + line );
            return;
        }

        final String key   = matcher.group( 1 ).trim().toLowerCase();
        final String value = matcher.group( 2 ).trim();

        if ( "".equals( value ) ) {
            map.put( key, true );
        } else if ( -1 == value.indexOf( ',' ) ) {
            map.put( key, value );
        } else {
            final String[] values = value.split( "," );

            for ( int i = 0; i < values.length; i++ ) {
                values[ i ] = values[ i ].trim();
            }
            map.put( key, Arrays.asList( values ) );
        }
    }
}




VB: type TSettings extends QObject
    FullName as string
    FavouriteFruit as string
    NeedSpelling as integer
    SeedsRemoved as integer
    OtherFamily as QStringlist
    
    Constructor
        FullName = ""
        FavouriteFruit = ""
        NeedSpelling = 0
        SeedsRemoved = 0
        OtherFamily.clear
    end constructor
end type

Dim Settings as TSettings
dim ConfigList as QStringList
dim x as integer
dim StrLine as string
dim StrPara as string
dim StrData as string

function Trim$(Expr as string) as string
    Result = Rtrim$(Ltrim$(Expr))
end function

Sub ConfigOption(PData as string)
    dim x as integer
    for x = 1 to tally(PData, ",") +1
        Settings.OtherFamily.AddItems Trim$(field$(PData, "," ,x))
    next
end sub 

Function ConfigBoolean(PData as string) as integer
    PData = Trim$(PData)
    Result = iif(lcase$(PData)="true" or PData="1" or PData="", 1, 0)
end function

sub ReadSettings
    ConfigList.LoadFromFile("Rosetta.cfg")
    ConfigList.text = REPLACESUBSTR$(ConfigList.text,"="," ")

    for x = 0 to ConfigList.ItemCount -1
        StrLine = Trim$(ConfigList.item(x))
        StrPara = Trim$(field$(StrLine," ",1))
        StrData = Trim$(lTrim$(StrLine - StrPara))  
    
        Select case UCase$(StrPara)
        case "FULLNAME"       : Settings.FullName = StrData 
        case "FAVOURITEFRUIT" : Settings.FavouriteFruit = StrData 
        case "NEEDSPEELING"   : Settings.NeedSpelling = ConfigBoolean(StrData)
        case "SEEDSREMOVED"   : Settings.SeedsRemoved = ConfigBoolean(StrData)
        case "OTHERFAMILY"    : Call ConfigOption(StrData)
        end select
    next
end sub

Call ReadSettings