Konfigurationsdatei parsen und auswerten



  • Hey, für meinen selbstgebautes InetServer-Utility habe ich eine simple Klasse geschrieben. die Konfigurationseinträge liest und auswertet.

    Eine Konfigurationsdatei sieht z.B. so aus.

    *** set ftp params and start ftp server ***
    ftp-port :: 21
    ftp-path :: C:\ftproot\
    ftp-start
    
    *** set http params and start web server ***
    http-port :: 80
    http-path :: C:\web\
    http-start
    

    Relevante Zeilen beginnen mit einem Schlüsselwort und nachstehenden Argumenten, getrennt durch ::
    Was Schlüsselwort ist wird zur Laufzeit bestimmt.
    Das sieht dann so aus:

    // Exec config file
            ConfigFile cf = new ConfigFile("serversettings.txt");
            cf.setAction("ftp-port", strings -> ftp.setPortTxt(strings[0]));
            cf.setAction("ftp-path", strings -> ftp.setPathTxt(strings[0]));
            cf.setAction("ftp-start", strings -> ftp.start());
            cf.setAction("http-port", strings -> web.setPortTxt(strings[0]));
            cf.setAction("http-path", strings -> web.setPathTxt(strings[0]));
            cf.setAction("http-start", strings -> web.start());
            cf.execute();
    

    Das zweite Argument von "setAction" ist die Handler-Funktion, die die einzelnen Argumente aus der Config-Datei als String[] bekommt.

    Die Klasse selbst ist hier:

    import java.io.IOException;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.util.ArrayList;
    import java.util.function.Consumer;
    import java.util.stream.Stream;
    
    /**
     * A line of the config file is organised as following:
     * keyword :: p1 :: p2 :: p3 ... pn
     *
     * :: is the delimiter
     * The arguments p1 ... pn are optional
     * Whitespaces are ignored
     * Lines that do not start with a known keyword are ignored
     * Blank lines are also ignored
     *
     * The usage is:
     *         ConfigFile cf = new ConfigFile("file_name_on_disk");
     *         cf.setAction("any_string", strings -> Command(strings));
     *         cf.setAction("other_string", strings -> Command(strings));
     *         ...
     *         cf.execute(); // Parse file and execute commands
     *
     * Commands are functions/methods that take a single String[] as argument
     * 
     */
    public class ConfigFile
    {
        private final String _path;
        private final ArrayList<Action> _list = new ArrayList<>();
    
        /**
         * Constructor
         * @param path set file path
         */
        public ConfigFile (String path)
        {
            _path = path;
        }
    
        /**
         * Action element
         */
        private class Action
        {
            final String name;
            final Consumer<String[]> function;
    
            Action (String n, Consumer<String[]> r)
            {
                name = n;
                function = r;
            }
        }
    
        /**
         * Submit a new action command
         * @param name Keyword
         * @param r Handler function
         */
        public void setAction (String name, Consumer<String[]> r)
        {
            _list.add(new Action (name, r));
        }
    
        /**
         * Parse line of config file and execute command
         * @param line the line
         */
        private void handleLine (String line)
        {
            line = line.replaceAll("\\s+","");
            String[] splits = line.split("::");
            for (Action a : _list)
            {
                if (splits[0].equals(a.name))
                {
                    String[] args = new String[splits.length-1];
                    System.arraycopy(splits, 1, args, 0, args.length);
                    a.function.accept(args);
                }
            }
        }
    
        /**
         * Parse whole config file and execute it line by line
         */
        public void execute()
        {
            try (Stream<String> stream = Files.lines(Paths.get(_path)))
            {
                stream.forEach(this::handleLine);
            }
            catch (IOException e)
            {
                System.out.println(e);
            }
        }
    }
    

    Läuft ab Java 8 aufwärts.
    Viel Spaß damit! 🙂



  • Ich habe die ArrayList gegen eine Hashmap getauscht. Dadurch entfällt die Action-Hilfsklasse und der Code ist kürzer. An der Funktionalität ändert sich aber nichts.

    Wenn jemanden die neue Version interessiert, werde ich sie posten.