Working with Configuration Files

Oct 20, 2016
Working with Configuration Files
  • Working with Configuration Files

    Learn more about reading and writing to configuration files and how to work with multiple files




    What Configuration Files Are For(top)

    As you develop, you will come across many instances where you will have to store data. A lot of the time, you can store this data in an object such as a HashMap or an ArrayList. So why use configuration files? The reason for this is that when the server is closed or restarts, it recreates everything and all the data you stored would have been lost. This is because objects such as those are stored in the virtual memory. In other words, just as easily as they were created, they are also destroyed.

    Now this is where files come in handy. Files are a way of saving data in a form that won't get deleted after your program is terminated. This is because files are no longer stored in virtual memory, but rather, on your actual storage disk. You can use this for storing information such as player balances, nicknames, and all sorts of data that you want to keep even after the server restarts.

    Let's get started.

    Using Single Configuration Files(top)

    The creation of the configuration file:
    Code (Java):

    private void createConfig() {
        try {
            if (!getDataFolder().exists()) {
                getDataFolder().mkdirs();
            }
            File file = new File(getDataFolder(), "config.yml");
            if (!file.exists()) {
                getLogger().info("Config.yml not found, creating!");
                saveDefaultConfig();
            } else {
                getLogger().info("Config.yml found, loading!");
            }
        } catch (Exception e) {
            e.printStackTrace();

        }

    }
     

    Checking If It Doesn't Exist(top)

    Code (Java):
    if (!getDataFolder().exists()) {
        getDataFolder().mkdirs();
    }
    This is a check to see if your plugin folder doesn't exists. The way Spigot/Bukkit manages plugin information is that each plugin has its own "data folder". These are the folders you see in your server's plugin folder named after the plugins containing important information such as their own individual configuration files. To get the path of this folder, you call the method getDataFolder() to return the File which is a path to what the server has designated as your plugin's Data Folder. The 'if' statement is checking whether or not the folder exists, and if it doesn't, it then calls the mkdirs() method (which basically creates the directory).

    Declaring the Configuration File(top)

    Code (Java):
    File file = new File(getDataFolder(), "config.yml");
    if (!file.exists()) {
        getLogger().info("config.yml not found, creating!");
        saveDefaultConfig();
    } else {
        getLogger().info("config.yml found, loading!");
    }
    This is where you declare your config file itself. To do this, you create a File object and construct it with the parameters 'getDataFolder()' and "config.yml". Like it was mentioned earlier, the getDataFolder() method returns a file which is the directory of your data folder. Now by putting it as the first parameter, it is telling your constructor that it will create a file named "config.yml" in the directory which is named by getDataFolder(). Now, that file isn't actually stored yet in your storage. It is still in virtual memory. The next 'if' statement checks whether or not the file exists and if it doesn't, it creates it and tells your plugin that this file is going to be 'my' config file. You should call saveDefaultConfig() to tell that this is how my default config file will be like.

    This is essentially all you need to create a quick configuration file, but remember to call it in your onEnable() method to make sure that you have a configuration ready before anything else happens.

    Using the Configuration File(top)

    To read and write to the config using the above method, we call the getConfig() method. However, if you will be calling getConfig() outside of your main class, you should use the main class's instance. If you do not know how to get instances from other classes, I suggest you check some of the other short guides on how to use constructors (the most commonly used). Once you have an instance, simply use that instance and call getConfig() from it.

    Now that you have the config, you can read and write to it using its different getter and setter methods. An example would be:
    Code (Java):
    // Reading from the config
    String name = plugin.getConfig().getString("player-name");

    // Writing to the config
    plugin.getConfig().set("player-name", name);
    What is it exactly? The "player-name" is your path in the config. If you've seen other YAML configuration files, you'll notice that they take the format of "label: value". To access the value of a particular path, you can use its name. However, you'll also notice that there are sometimes "sub-paths" wherein there are labels that belong under another label.

    Code (YAML):
    player-name: Steve

    player
    :
      time
    :
        join
    : 6:00pm
    To access the value of something that's a sub-path, you can simply use '.' to indicate a lower level like so:
    Code (Java):
    // Reading from the config
    String time = plugin.getConfig().getString("player.time.join");

    // Writing to the config
    plugin.getConfig().set("player.time.join", time);
    The plugin will read the '.' as an indicator that "Oh! I should check the sub-path."

    Note that although I used a String in the getting and setting examples, you can use all sorts of different types as well. For the getters, there exists getInt(), getBoolean(), getList(), and many more. For the setters, it simply takes in the path as the first parameter and an Object as the second. This means that you can set basically any Object.

    An important thing to note, however, is that after you read and/or write to a configuration file, you should always remember to save the data if you want it to be saved to the file. To do this, you should do :
    Code (Java):
    plugin.saveConfig();
    Configuration has all sorts of fun tricks and tools that you can use to make the best plugin you can make. Use it properly and it can be one of your most powerful assets.

    Using Multiple Configuration Files(top)

    Creating the Files(top)

    First of all, you'll want to be able to make your File and FileConfiguration objects available to other classes in your plugin so that you can readily read and write to your different configuration files. How do you do this?

    In your main class, create field variables. These are variables that are not contained within a method so that they can be accessed externally.
    Code (Java):
    public class Main extends JavaPlugin {

        private File configf, specialf;
        private FileConfiguration config, special;

        @Override
        public void onEnable(){
            createFiles();
        }

        public FileConfiguration getSpecialConfig() {
            return this.special;
        }

        private void createFiles() {

            configf = new File(getDataFolder(), "config.yml");
            specialf = new File(getDataFolder(), "special.yml");

            if (!configf.exists()) {
                configf.getParentFile().mkdirs();
                saveResource("config.yml", false);
            }
            if (!specialf.exists()) {
                specialf.getParentFile().mkdirs();
                saveResource("special.yml", false);
             }

            config = new YamlConfiguration();
            special = new YamlConfiguration();
            try {
                config.load(configf);
                special.load(specialf);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
     
    What does this do? It's a snapshot of how a basic main class would look like. What else it does is that it creates two configuration files, namely, "config.yml" and "special.yml". When the plugin is enabled, it calls the createFiles() method. What this does is that for each File object, it checks if it exists. If it doesn't, it creates it. This part can be better explained in Using Single Configuration Files.

    What about the saveResource(String, boolean) part? You can actually store files inside your jar aside from just classes. To do this, depending on your IDE, you should create a new file in your 'src' folder (names may vary depending on editor). Now in your main class, you can call saveResource("name of file in jar here", replaceIfAlreadyExists). This will save the file stored in your jar to the file <data folder>/<name of file in jar> if it doesn't already exist (or if the boolean was true). Now, you've created the multiple configuration files!

    Reading and Writing to Multiple Files(top)

    We can do this:
    Code (Java):
    plugin.getSpecialConfig().getString("some-path");
    Basically, you can access the configuration the same way as you would do getConfig() from Using Single Configuration Files. If you want to see more on how to manipulate and access configurations, read that section. As for saving, for custom configurations you need to call FileConfiguration#save(File) (which saveConfig() does under the hood for config.yml) to write the data to the disk.
  • Loading...
  • Loading...