I'm currently still learning c# and im trying to find the best method to get the information out. Tried Regex and even thought of using JSON but im pretty sure there is a simpler method. I have data like this:
Main_name = {
# Comment
# Comment
# Comment
type1 = uselessname_importantNumber (e.g. ryu_3)
type2 = "path" # Comment
type3 = name
type4 = true
type5 = {
name2
name3...
# Comment
}
}
My objective is to store the values: Main_name, importantNumber, path, name, true, list of names in type5 in a List.
Currently im doing
TechData = new List<ClassTech>();
string[] paths = Directory.GetFiles(path, "*.txt");
foreach (string pathsl in paths)
{
using (StreamReader sr = File.OpenText(pathsl))
{
string line;
int i = 0;
string[] words;
while ((line = sr.ReadLine()) != null)
{
if (line.Contains("{") == true && !line.Contains("#"))
{
// Get's the name
words = line.Split('=');
TechData.Add(new ClassTech(words[0].Trim(' '), "None", -1, null, "None", null, true));
// In {}
while ((line = sr.ReadLine()) != null)
{
if ((Regex.Match(line, @"\bera\b")).Success && (TechData[i].era == -1) && !line.Contains("#"))
{
words = line.Split('=');
TechData[i].era = words[1][words[1].Length - 1] - 48;
}
else if ((Regex.Match(line, @"\btexture\b")).Success && (TechData[i].texture == null) && !line.Contains("#"))
{
words = line.Split('=');
TechData[i].texture = words[1].Trim(' ', '"');
}
else if ((Regex.Match(line, @"\bcategory\b")).Success && (TechData[i].category == null) && !line.Contains("#"))
{
words = line.Split('=');
TechData[i].category = words[1].Trim(' ');
}
else if ((Regex.Match(line, @"\bcan_research\b")).Success && (Regex.Match(line, @"\bno\b")).Success && !line.Contains("#"))
{
TechData[i].canResearch = false;
}
else if ((Regex.Match(line, @"\bmodifier\b")).Success && !line.Contains("#"))
{
while ((line = sr.ReadLine()) != null)
{
if (line.Contains("}")) { break; }
else if (line.Contains("="))
{
TechData[i].modifiers.Add(line.Trim(' '));
}
else { }
}
}
else if ((Regex.Match(line, @"\bunlocking_technologies\b")).Success && !line.Contains("#"))
{
while ((line = sr.ReadLine()) != null)
{
if (line.Contains("}")) { break; }
else if (!string.IsNullOrEmpty(line) && !string.IsNullOrWhiteSpace(line))
{
TechData[i].restrictions.Add(line.Trim('\t'));
}
else { }
}
}
else if (line.Contains("}") == true)
{
break;
}
else
{
}
}
i ;
}
}
}
}
The problem is if the data becomes bigger, it will start to become harder and harder so my question is: is there a simpler way to do it and if possible faster?
Data example
sericulture = {
# Unlocks Mulberry Groves PM on Rice Farms
era = era_1
texture = "gfx/interface/icons/invention_icons/sericulture.dds"
category = production
can_research = no
modifier = {
building_silk_plantation_throughput_mult = 0.25
}
}
enclosure = {
# Unlocks construction of Farms and Plantations
era = era_1
texture = "gfx/interface/icons/invention_icons/enclosure.dds"
category = production
}
manufacturies = {
# Unlocks Mercantilism Law
# Unlocks Food Industry, Textile Mills, Furniture Manufacturies, Glassworks, Tooling Workshops, Paper Mills
era = era_1
texture = "gfx/interface/icons/invention_icons/manufacturies.dds"
category = production
}
shaft_mining = {
# Unlocks Coal Mine, Iron Mine, Lead Mine, Sulfur Mine
era = era_1
texture = "gfx/interface/icons/invention_icons/shaft_mining.dds"
category = production
unlocking_technologies = {
enclosure
manufacturies
}
}
atmospheric_engine = {
# Unlocks Motor Industry
# Unlocks Atmospheric Engine Pump PM in Coal Mine, Iron Mine, Lead Mine, Sulfur Mine
era = era_1
texture = "gfx/interface/icons/invention_icons/atmospheric_engine.dds"
category = production
unlocking_technologies = {
shaft_mining
}
}
CodePudding user response:
I broadly agree with @Jon Skeet's suggestion to convert these files to JSON. If you can do that at the source, do it.
If not, you'll either have to convert it yourself, or parse the data some other way.
Regardless, if you want this to be expandable, your goal should be to be able to get this data into C# without relying on beforehand knowledge of any property names.
I've put together a parser based on the example files you've left above. It's not perfect, but it should be a strong starting point:
The full project, and the primary parsing logic
It works by parsing the input file to a string-keyed dictionary containing values of Dictionary<string,object?>
, List<string>
, or object?
.
Note: if you want to convert this JSON data to C# objects afterwards, go for it. It'll be much simpler once it's in JSON form, since there are many tools for that.
Example usage
SourceFile.txt
Main_name = {
# Comment
# Comment
# Comment
type1 = ryu_3
type2 = "path" # Comment
type3 = name
type4 = true
type5 = {
name2
name3...
# Comment
}
}
Program.cs
var outVal = new ObjectParserThing.ObjectParserThing().ParseFile("sourceFile.txt");
Console.WriteLine(JsonSerializer.Serialize(outVal, new JsonSerializerOptions {
WriteIndented = true,
}));
Output
{
"Main_name": {
"type1": "ryu_3",
"type2": "\u0022path\u0022",
"type3": "name",
"type4": "true",
"type5": [
"name2",
"name3..."
]
}
}