Click here to Skip to main content
15,905,563 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a text file which I am receiving its contents through a formatted string which is as this:
TABLE OperatorPoints \r\nHEADING\r\nDGName InstanceName OP1_X OP1_Y OP2_X OP2_Y\r\nDATA\r\nG1[1,1] L1[1,1] 251.8419 -804.6282 768.8362 -290.5563\r\nG1[1,1] die[1,1] 357.8950 -714.6857 652.0683 -395.6490\r\nEND
Formatted in the text file looks as below
TABLE OperatorPoints 
HEADING
DGName                  InstanceName        OP1_X        OP1_Y        OP2_X        OP2_Y
DATA
G1[1,1]                      L1[1,1]     251.8419    -804.6282     768.8362    -290.5563
G1[1,1]                   valve[1,1]     357.8950    -714.6857     652.0683    -395.6490
END

Contents my vary however the Headers (DGName, InstanceName etc) are always the same.

I am only interested in the values and need to be able to read each value and store it in a class object. As contents values my vary example instead of G1[1,1] there might be longer text, and so for the other cells. There also might be missing cells example 251.8419 in OP1_X missing. What I have in my mind is have a dictionary <string,int> where I place the headers and the 'cell' width so that I can then read the values based on an exact location.

What I have tried:

Right now I am seperating each line
string[] result = myString.Split(new string[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
then use foreach on each line. But the disadvantage if the is a missing value all the remaining values for that line will move to the left thus I end up with a missing value in the last column
Posted
Updated 28-Sep-18 5:50am
Comments
Richard MacCutchan 28-Sep-18 11:29am    
Don't remove empty entries.

1 solution

If can remove the lines containing TABLE OperatorPoints ,HEADING,Data, and END
you can pass the file stream to this class. I used it to take a CSV file and return a data table. Looking at the sample file I am assuming the data is tab delimited. That being the case you will need to modify the class to use tab for the deliminter instead of commas.
Good Luck

public class CsvParser
    {
        public static DataTable Parse(string data, bool headers)
        {
            return Parse(new StringReader(data), headers);
        }

        public static DataTable Parse(string data)
        {
            return Parse(new StringReader(data));
        }

        public static DataTable Parse(TextReader stream)
        {
            return Parse(stream, false);
        }

        public static DataTable Parse(TextReader stream, bool headers)
        {
            DataTable table = new DataTable();
            CsvStream csv = new CsvStream(stream);
            string[] row = csv.GetNextRow();
            if (row == null)
                return null;
            if (headers)
            {
                foreach (string header in row)
                {
                    if (header != null && header.Length > 0 && !table.Columns.Contains(header))
                        table.Columns.Add(header, typeof(string));
                    else
                        table.Columns.Add(GetNextColumnHeader(table), typeof(string));
                }
                row = csv.GetNextRow();
            }
            while (row != null)
            {
                while (row.Length > table.Columns.Count)
                    table.Columns.Add(GetNextColumnHeader(table), typeof(string));
                table.Rows.Add(row);
                row = csv.GetNextRow();
            }
            return table;
        }

        private static string GetNextColumnHeader(DataTable table)
        {
            int c = 1;
            while (true)
            {
                string h = "Column" + c++;
                if (!table.Columns.Contains(h))
                    return h;
            }
        }

        private class CsvStream
        {
            private TextReader stream;

            public CsvStream(TextReader s)
            {
                stream = s;
            }

            public string[] GetNextRow()
            {
                ArrayList row = new ArrayList();
                while (true)
                {
                    string item = GetNextItem();
                    if (item == null)
                        return row.Count == 0 ? null : (string[])row.ToArray(typeof(string));
                    row.Add(item);
                }
            }

            private bool EOS = false;
            private bool EOL = false;

            private string GetNextItem()
            {
                if (EOL)
                {
                    // previous item was last in line, start new line
                    EOL = false;
                    return null;
                }

                bool quoted = false;
                bool predata = true;
                bool postdata = false;
                StringBuilder item = new StringBuilder();

                while (true)
                {
                    char c = GetNextChar(true);
                    if (EOS)
                        return item.Length > 0 ? item.ToString() : null;

                    if ((postdata || !quoted) && c == ',')
                        // end of item, return
                        return item.ToString();

                    if ((predata || postdata || !quoted) && (c == '\x0A' || c == '\x0D'))
                    {
                        // we are at the end of the line, eat newline characters and exit
                        EOL = true;
                        if (c == '\x0D' && GetNextChar(false) == '\x0A')
                            // new line sequence is 0D0A
                            GetNextChar(true);
                        return item.ToString();
                    }

                    if (predata && c == ' ')
                        // whitespace preceeding data, discard
                        continue;

                    if (predata && c == '"')
                    {
                        // quoted data is starting
                        quoted = true;
                        predata = false;
                        continue;
                    }

                    if (predata)
                    {
                        // data is starting without quotes
                        predata = false;
                        item.Append(c);
                        continue;
                    }

                    if (c == '"' && quoted)
                    {
                        if (GetNextChar(false) == '"')
                            // double quotes within quoted string means add a quote       
                            item.Append(GetNextChar(true));
                        else
                            // end-quote reached
                            postdata = true;
                        continue;
                    }

                    // all cases covered, character must be data
                    item.Append(c);
                }
            }

            private char[] buffer = new char[4096];
            private int pos = 0;
            private int length = 0;

            private char GetNextChar(bool eat)
            {
                if (pos >= length)
                {
                    length = stream.ReadBlock(buffer, 0, buffer.Length);
                    if (length == 0)
                    {
                        EOS = true;
                        return '\0';
                    }
                    pos = 0;
                }
                if (eat)
                    return buffer[pos++];
                else
                    return buffer[pos];
            }
        }
    }
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900