Skip to content

Additional DataFile Functionality

Jimmy Cushnie edited this page Nov 12, 2019 · 5 revisions

ReadOnlyDataFile

ReadOnlyDataFile is a version of DataFile without any of the functions that save data. It's good if you want your program to read a configuration file without accidentally changing it.

var file = new ReadOnlyDataFile("test");
string testString = file.Get("key", "value"); // this is fine
file.Set("key", "value"); // CS1061: 'ReadOnlyDataFile' does not contain a definition for 'Set'

Default Files

When you create a new DataFile, if that file does not already exist on disk, it will be created. By default this creates an empty file, but it can also create a file with text that you specify.

In the standalone version of SUCC, you directly supply a string with the contents of the default file. In the Unity version, you give it the name of a TextAsset with the contents of the default file. See Version Differences for more.

// STANDALONE

static readonly string ConfigDefaultFile = 
@"
# This is the config file for my program.
# Feel free to modify any values in here. They don't do anything.

UselessNumber           : 568.44
Another Useless Number  : 22.5
";

// if there isn't already a file called ProgramConfig.succ, it will created with ConfigDefaultFile as its contents
static DataFile Config = new DataFile("ProgramConfig", defaultFileText: ConfigDefaultFile);
// UNITY

// if there isn't already a file called ProgramConfig.succ, it will created with ConfigDefaultFile.txt (found in the Resources folder) as its contents
static DataFile Config = new DataFile("ProgramConfig", defaultFile: "ConfigDefaultFile");

AutoSave

Usually, when you change some data in a file, it will automatically save that data to disk. This behavior can be disabled if DataFile.AutoSave is false. If AutoSave is off, you will need to call DataFile.SaveAllData() manually.

var file = new DataFile("test");
file.Set("number", 1234); // this will modify the file on disk
file.AutoSave = false;
file.Set("number", 5678); // this will modify the file in memory only; the file on disk is unchanged. 'number' is 1234 on disk and 5678 in memory.
file.SaveAllData(); // now 'number' is 5678 both in memory and on disk

Note that all DataFile constructors have an option value for setting the starting state of AutoSave.

AutoReload

By default, SUCC will ignore any changes to configuration files that happen while the program is running. However, if you turn DataFile.AutoReload to true, the DataFile will reload all its data from disk whenever the file is changed on disk. If AutoReload is false, you can still reload all data from disk by calling DataFile.ReloadAllData manually.

There is also a DataFile.OnAutoReload event for triggering custom behavior when an auto-reload happens (usually re-loading the values from the file).

var file = new ReadOnlyDataFile("test", autoReload: true);
file.OnAutoReload += () => Console.WriteLine("test file was changed");

FilePath and FileName

Respectively, these properties refer to the path and name of the file on disk. FileName will not include a file extension.

SizeOnDisk

Returns the size of the file on disk in bytes.

DeleteKey()

DataFile.DeleteKey(string key) will delete all the data under the key key in the file.

GetRawText() and GetRawLines()

DataFile.GetRawText() returns a single string with all of the text of the file as it exists in memory. If the file has more than one line, it will contain newline characters.

DataFile.GetRawLines() returns an array of strings, each corresponding to a line in the file as it exists in memory. None of the strings will contain newline characters.

GetTopLevelKeysInOrder()

Returns a string array containing each top-level key in the file.

For example, calling GetTopLevelKeys() on this file:

item1: 1234
list of things that suck:
    - war
    - slavery
    - your mom when she comes to my house each friday night
position:
    x: 0
    y: 100
    z: 0

would return an array containing "item1", "list of things that suck", and "position".

TopLevelKeys

This is like GetTopLevelKeysInOrder() except it returns an IReadOnlyCollection<string> rather than a string[]. As the naming implies, TopLevelKeys is not guaranteed to be in the same order as they appear in the file. However, it is much faster than GetTopLevelKeysInOrder.

KeyExists(string key)

Returns a boolean value to test if a top-level key exists in the file. Similar to calling TopLevelKeys.Contains(string key) but it's slightly faster.

GetAtPath() and SetAtPath()

These functions allow you to get and set data at nested paths within the file.

var file = new DataFile("example");
file.SetAtPath(69, "a", "b", "c");
a:
    b:
        c: 69

Save/Get as Object

You can save or load an entire file as an object using the same rules as Complex Types (i.e. they will respect custom complex type rules). For example:

using SUCC;

public class VideoConfig
{
    public int resolutionX = 1920;
    public int resolutionY = 1080;
    public bool fullScreen = true;
}

static class Program
{
    static void Main()
    {
        var videoFile = new DataFile("video");
        videoFile.SaveAsObject(new VideoConfig());
    }
}

this code will create a file that looks like this:

resolutionX: 1920
resultionY: 1080
fullScreen: true

and you can load videoFile as a VideoConfig like so:

var videoConfig = videoFile.GetAsObject<VideoConfig>();

note if you do this that SUCC will ignore any extra data in the file. For example, the file above and the following file would load as the exact same VideoConfig:

whatsForDinner: "ice cream"
resolutionX: 1920
best numbers:
	- 69
	- 69.69
	- 6969
resultionY: 1080
fullScreen: true

Save/Get as Dictionary

Similar to Save/Get as Object, you can save and load an entire file as a Dictionary. There are a few restrictions on this, however:

var file = new DataFile("test");

var dicc = new Dictionary<string, float>()
{
    ["genitals to mouth"] = 69,
    ["butt to back of head"] = 96,
    ["fraction of the history of the universe that you, personally, will get to experience"] = 0,
};

file.SaveAsDictionary(dicc);

this code will create a file that looks like this:

genitals to mouth: 69
butt to back of head: 96
fraction of the history of the universe that you, personally, will get to experience: 0

You can later retrieve the saved dictionary with

file.GetAsDictionary<string, float>();

Non-Generic Methods

There are non-generic versions of Get, Set, SaveAsObject, and SaveAsDictionary. With these non-generic versions, you pass them a System.Type value instead of passing the type through generics.

You will probably never need to use these methods. Use the generics wherever possible; they make for much neater code.

MemoryDataFile and MemoryReadOnlyDataFile

These are versions of DataFile and ReadOnlyDataFile which do not correspond to actual files on disk; rather, they save and load data in program memory. They function identically to DataFile and ReadOnlyDataFile except that they are missing members which relate to disk storage like AutoReload and FileName.

Memory files have two use cases:

  • when you want to read a SUCC file within a zipped folder - Logic World uses this in its modding system
  • when you want to test the functionality of DataFiles without writing anything to disk - SUCC's unit tests do this

Both memory file types have a ConvertToFileOnDisk() method which will save the file to disk.