Alika87
Alika87

Reputation: 311

C#: Loop over Textfile, split it and Print a new Textfile

I get many lines of String as an Input that look like this. The Input is a String that comes from

theObjects.Runstate;

each @VAR;****;@ENDVAR; represents one Line and one step in the loop.

@VAR;Variable=Speed;Value=Fast;Op==;@ENDVAR;@VAR;Variable=Fabricator;Value=Freescale;Op==;@ENDVAR;

I split it, to remove the unwanted fields, like @VAR,@ENDVAR and Op==. The optimal Output would be:

Speed = Fast; 
Fabricator = Freescale; and so on.

I am able to cut out the @VAR and the@ENDVAR. Cutting out the "Op==" wont be that hard, so thats now not the main focus of the question. My biggest concern right now is,thatI want to print the Output as a Text-File. To print an Array I would have to loop over it. But in every iteration, when I get a new line, I overwrite the Array with the current splitted string. I think the last line of the Inputfile is an empty String, so the Output I get is just an empty Text-File. It would be nice if someone could help me.

string[] w;
Textwriter tw2;
foreach (EA.Element theObjects in myPackageObject.Elements)
{
    theObjects.Type = "Object";
    foreach (EA.Element theElements in PackageHW.Elements)
    {
        if (theObjects.ClassfierID == theElements.ElementID)
        {
            t = theObjects.RunState;
            w = t.Replace("@ENDVAR;", "@VAR;").Replace("@VAR;", ";").Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);

            foreach (string s in w)
            {
                tw2.WriteLine(s);
            }
        }
    }
}

Upvotes: 0

Views: 239

Answers (1)

Tim Schmelter
Tim Schmelter

Reputation: 460108

This linq-query gives the exptected result:

var keyValuePairLines = File.ReadLines(pathInputFile)
    .Select(l =>
    {
        l = l.Replace("@VAR;", "").Replace("@ENDVAR;", "").Replace("Op==;", "");
        IEnumerable<string[]> tokens = l.Split(new[]{';'}, StringSplitOptions.RemoveEmptyEntries)
            .Select(t => t.Split('='));
        return tokens.Select(t => {
            return new KeyValuePair<string, string>(t.First(), t.Last());
        });
    });

foreach(var keyValLine in keyValuePairLines)
    foreach(var keyVal in keyValLine) 
        Console.WriteLine("Key:{0} Value:{1}", keyVal.Key, keyVal.Value);

Output:

Key:Variable         Value:Speed
Key:Value            Value:Fast
Key:Variable         Value:Fabricator
Key:Value            Value:Freescale

If you want to output it to another text-file with one key-value pair on each line:

File.WriteAllLines(pathOutputFile, keyValuePairLines.SelectMany(l => 
    l.Select(kv => string.Format("{0}:{1}", kv.Key, kv.Value))));

Edit according to your question in the comment:

"What would I have to change/add so that the Output is like this. I need AttributeValuePairs, for example: Speed = Fast; or Fabricator = Freescale ?"

Now i understand the logic, you have key-value pairs but you are interested only in the values. So every two key-values belong together, the first value of a pair specifies the attibute and the second value the value of that attribute(f.e. Speed=Fast).

Then it's a little bit more complicated:

var keyValuePairLines = File.ReadLines(pathInputFile)
    .Select(l =>
    {
        l = l.Replace("@VAR;", "").Replace("@ENDVAR;", "").Replace("Op==;", "");
        string[] tokens = l.Split(new[]{';'}, StringSplitOptions.RemoveEmptyEntries);
        var lineValues = new List<KeyValuePair<string, string>>();
        for(int i = 0; i < tokens.Length; i += 2)
        {
            // Value to a variable can be found on the next index, therefore i += 2
            string[] pair = tokens[i].Split('=');
            string key = pair.Last();
            string value = null;
            string nextToken = tokens.ElementAtOrDefault(i + 1);
            if (nextToken != null)
            { 
                pair = nextToken.Split('=');
                value = pair.Last();
            }
            var keyVal = new KeyValuePair<string, string>(key, value);
            lineValues.Add(keyVal);
        }
        return lineValues;
    });

File.WriteAllLines(pathOutputFile, keyValuePairLines.SelectMany(l => 
    l.Select(kv=>string.Format("{0} = {1}", kv.Key, kv.Value))));

Output in the file with your single sample-line:

Speed = Fast
Fabricator = Freescale

Upvotes: 1

Related Questions