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.