Working with Configuration Files

Discussion in 'Wiki Discussion' started by jflory7, May 22, 2015.

  1. jflory7

    Retired Benefactor

    Working with Configuration Files

    Working with Configuration Files

    Learn more about reading and writing to configuration files and how to work with custom configuration 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 Default Configuration Files(top)

    The creation of the configuration file:
    Code (Java):
    plugin.saveDefaultConfig();
    saveDefaultConfig() will write the config.yml file from your plugin's jar file to the plugin's data folder. (If that folder doesn't exist it will be created) It will not overwrite an existing config file.

    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 write to a configuration file, you should always remember to call saveConfig() if you want the data to be saved to the file. (Warning: saveConfig() will remove all your comments that aren't at the top before the first key)
    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 Custom Configurations(top)

    Creating the File(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 YourPlugin extends JavaPlugin {

        private File customConfigFile;
        private FileConfiguration customConfig;

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

        public FileConfiguration getCustomConfig() {
            return this.customConfig;
        }

        private void createCustomConfig() {
            customConfigFile = new File(getDataFolder(), "custom.yml");
            if (!customConfigFile.exists()) {
                customConfigFile.getParentFile().mkdirs();
                saveResource("custom.yml", false);
             }

            customConfig= new YamlConfiguration();
            try {
                customConfig.load(customConfigFile);
            } catch (IOException | InvalidConfigurationException e) {
                e.printStackTrace();
            }
        }
    }
     
    What does this do? It's a snapshot of how a basic plugin class would look like. What else it does is that it creates a configuration file, namely, "custom.yml". When the plugin is enabled, it calls the createCustomConfig() method. It checks if the File object of the custom config exists and if it doesn't it creates the parent directory and the file.

    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 custom configuration files!

    Reading and Writing to Custom Files(top)

    We can do this:
    Code (Java):
    plugin.getCustomConfig().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.
     
    • Like Like x 1
    • Useful Useful x 1
  2. This should be titled custom or data configuration files. For the config.yml where you keep static data or settings, all you have to do is create a config.yml in the same directory as your plugin.yml and set your defaults in the file, then do saveDefaultConfig in onEnable and saveConfig in onDisable.
     
  3. jflory7

    Retired Benefactor

    @Bolt
    Thanks for contributing this awesome piece. I just went and wiki-ified it, so hopefully this should make it easier to read for anyone who is looking to learn. All of the information was there, and all I did was organize it a bit. Full credit goes to you on this one; this was really well-documented. Nice job! :)
     
  4. @jflory7
    Thanks! I'll try to improve my tutorials for better readability next time hahaha :)
     
    • Like Like x 1
  5. Thanks to share.
     
    • Like Like x 1
  6. Nice,Thanks :)
     
    • Like Like x 1
  7. This is a very well written article. I appreciate the effort and time you took!
    Thank you very much it helps me starting up a little bit better as I understand every piece of code and if I don't I'll read the context.
     
    • Agree Agree x 2
  8. Might be a good idea to add a section on reloading/saving custom config files.
     
    • Agree Agree x 3
  9. Your problem is that you don't export your jar file with a config.yml in the export path... saveResource accesses/saves a copy of what's in the jar (which you can explore by unarchiving it using WinRAR or something similar)
     
  10. I'm really sorry but can you show me step by step how to export my jar file with a config.yml in the export path? I'm a noob with java and this is my first plugin.
     
  11. Depends on what IDE you use. If you use Eclipse, your project folder needs to look like this.
    upload_2017-12-4_0-29-37.png
     
  12. So, is doing saveDefaultConfig(); bad?
     
  13. If by "bad" you mean your current config in memory (getConfig()) won't write if the file already exists, yes. If you want the file to be named something different than config.yml, then also yes.
    Otherwise, no, it's not bad. It saves the config file from the .jar file to the plugin directory if it doesn't exist already, but other than that... doesn't do much else.
     
  14. I think a section about programmatic defaults would be a nice addition.

    You can create a config file this way:

    Code (Text):
    // instead of this.getConfig().set()
    this.getConfig().addDefault("login cooldown (min)", 60);

    // The configuration saver of the API will ignore all of the default values unless we specify to "copy the defaults". Defaults never override the settings of the user.
    this.getConfig().options().copyDefaults(true);

    this.saveConfig();
    (No need to create config.yml inside the plugin project folder)


    I think using programmatic defaults has at least one advantage: You can use class constants for the config value access paths and thus you don't have to type the names twice (because you don't need to write a config.yml).

    How I mean the usage of constants:
    Code (Text):

    this.getConfig().addDefault(PATH_TO_LOGIN_COOLDOWN_IN_CONFIG, 60);
     

    Also, there is no need to create the data folder. Bukkit does it.
     

Share This Page