【问题标题】:Splitting a large text file to form a table拆分大文本文件以形成表格
【发布时间】:2014-01-07 13:45:13
【问题描述】:

我有一个文本文件,我必须读取文本文件,然后将文件数据转换为表格形式。 文件就是这种形式

{KeyValuePair}
{
    Key1 = Value1 {next}
    Key2 = Value2 {next}
    Key3 = Value3 {next}
    Key4 = {KeyValuePair}   {
                                KeyA = ValueA {next}
                                KeyB = ValueB {next}
                                KeyC = ValueC {next}
                            }
}

我需要这样的输出

我的逻辑代码在这里

StreamReader reader = new StreamReader("C:\\Users\\Kaushik Kishore\\Documents\\TextToRead.txt");
            string data = reader.ReadToEnd();
            //string[] stringSeparater = new string[] { "{KeyValuePair}" };
            //string[] getData = data.Split(stringSeparater, StringSplitOptions.None);
            //string[] separater = new string[] { "{next}" };
            //string[] nextSplit = data.Split(separater, StringSplitOptions.None);
            string pattern = @"(=)|(next)|(KeyValuePair)|({)|(})";
            string[] output = Regex.Split(data, pattern);
            foreach (string one in output)
            {
                Response.Write(one);

            }

所以我面临的问题是如何编写实际的逻辑来提取所需的字符串。 Next 指定我们必须更改表中的行。每次出现下一个关键字时,我都必须在新行中发布数据。 提前致谢

编辑 我做了一些努力并写了一些代码 这是打印数据现在我想知道如何将数据从控制器传递到视图。当数据进入循环部分时。

public ActionResult Index()
        {


            StreamReader reader = new StreamReader("C:\\Users\\Kaushik Kishore\\Documents\\Text2.txt");
            string data = reader.ReadToEnd();
            // replacing all tabs white space new line and everything
            string trimmedData = Regex.Replace(data, @"\s", "");
            string pattern = @"({next})|({KeyValuePair}{)|(}{next})";
            string[] output = Regex.Split(trimmedData, pattern);
            int length = output.Length;
            int count = 0;
            foreach (string one in output)
            {
                count++;
                if (one == "{KeyValuePair}{")
                {
                    Response.Write("Table Create</br>");
                }
                else if (count == length)
                {
                    string[] last = one.Split('=');
                    foreach (string lastVal in last)
                    {
                        Response.Write(lastVal.Substring(0,lastVal.Length-1));
                        Response.Write('|');
                    }
                }
                else
                {                                        
                    string[] keyVal = one.Split('=');
                    foreach (string val in keyVal)
                    {
                        if (val == "{next}")
                        {
                            Response.Write("</br>");                            
                        }
                        else if (val == "}{next}")
                        {
                            Response.Write("Subtable End</br>");                            
                        }
                        else if (val == "}")
                        {
                            Response.Write("");                            
                        }
                        else
                        {
                            Response.Write(val);
                            Response.Write("|");
                        }
                    }
                }
            }
            reader.Close();
            return View();
        }

【问题讨论】:

  • @SamLeach 我已经提到了文本文件格式。以上请通过。

标签: c# regex loops logic


【解决方案1】:

这将是您的控制器部分

public ActionResult Index()
    {
        ViewBag.DisplayTable = GetKeyValueDisplayContent(@"YourFilePath.Txt");
        return View();
    }

    private string GetKeyValueDisplayContent(string fileToRead)
    {
        // 01 Get Data
        string DataToProcess = GetDataToProcess(fileToRead);

        // 02 Cleaning Data (replacing all tabs white space new line and everything)
        DataToProcess = CleanDataToProcess(DataToProcess);

        // 03 Retrieve Array from Data format
        string[] output = GetDataInArray(DataToProcess);

        // 04 Displaying Result
        string DrawTable = GetDisplayHTML(output);
        return DrawTable;

    }

    private string GetDataToProcess(string fileToRead)
    {

        StreamReader reader = new StreamReader(fileToRead);
        string data = reader.ReadToEnd();
        reader.Close();

        return data;
    }

    private string CleanDataToProcess(string dataToProcess)
    {
        return Regex.Replace(dataToProcess, @"\s", "");
    }

    private string[] GetDataInArray(string dataToProcess)
    {
        string pattern = @"({next})|({KeyValuePair}{)|(}{next})";
        string[] output = Regex.Split(dataToProcess, pattern);

        return output;
    }

    private string GetDisplayHTML(string[] output)
    {
        int length = output.Length;
        int count = 0;
        StringBuilder OutputToPrint = new StringBuilder();


        foreach (string one in output)
        {

            if (one == "{KeyValuePair}{")
            {
                count++;
                if (count >= 2)
                {
                    OutputToPrint.Append("<td><table border = \"1\">");
                }
                else
                {
                    OutputToPrint.Append("<table border = \"1\">");
                }
            }
            else if (one.Contains("=") == true)
            {
                string[] keyVal = Regex.Split(one, @"=");
                OutputToPrint.Append("<tr>");
                foreach (string val in keyVal)
                {
                    if (val != "")
                    {
                        OutputToPrint.Append("<td>");
                        OutputToPrint.Append(WebUtility.HtmlEncode(val));
                        OutputToPrint.Append("</td>");

                    }
                }

            }
            else if (one.Equals("{next}"))
            {
                OutputToPrint.Append("</tr>");
            }
            else if (one.Contains("}{next}") == true)
            {
                OutputToPrint.Append("</table></td>");
            }
            else if (one == "}")
            {
                OutputToPrint.Append("</table>");
            }
            else { }
        }

        return OutputToPrint.ToString();
    }

这将是视图

<div>
@Html.Raw(ViewBag.DisplayTable)
</div>

希望你能找到这个

【讨论】:

    【解决方案2】:

    如果你使用这个小模式,如果你在值捕获组上递归使用它,我想你可以获得你想要的:

    string pattern = @"(?>\s*(?<key>[^\s=]+)\s*=\s*|^\s*)(?>{KeyValuePair}\s*{\s*(?<value>(?>(?<c>{)|(?<-c>})|[^{}]+)+(?(c)(?!)))\s*}|(?<value>[^\s{]+)\s*(?<next>{next})\s*)";
    

    图案细节:

    (?>                            # possible begin of the match
        \s*(?<key>[^\s=]+)\s*=\s*    # a keyname
      |                             # OR
        ^\s*                         # the start of the string
    )
    
    (?>
        # case KeyValuePair #
        {KeyValuePair} \s* { \s*  
        (?<value> 
            (?>(?<c>{)|(?<-c>})|[^{}]+)+ (?(c)(?!)) # content inside balanced curly brackets*
        )
        \s* }
      |    OR
        # case next #
        (?<value>
            [^\s{]+  # all that is not a white character or an opening curly bracket
        )
        \s*
        (?<next> {next} )\s* # the goal of this capture is to know in which case you are
    )
    

    (*)你可以在这里找到更多关于平衡组的解释:What are regular expression Balancing Groups?

    这个想法是编写一个递归方法,当模式匹配“keyValuePair”情况时,该方法将调用自身。在“下一个”情况下,该方法仅在数组(或这种结构)中记录键/值。该方法必须返回这种数组。

    【讨论】:

    • 你能解释一下我如何制作自己的图案吗?我是这个C# 的新手,所以如果你能解释一下,我将不胜感激。这在\s 序列中显示错误。
    • @Kaushik:如果您不想将每个反斜杠加倍,则必须使用原始字符串 (string pattern = @"...";)。我不是 C# 专家,这就是为什么我不能为您提供该方法的完整代码的原因,但想法就在这里(它是一个递归函数)。由于模式有点长,我无法描述每个符号,但是您会在regular-expressions.info 中找到更多信息,您可以在regexstorm.net/tester 中测试模式
    • 我正在尝试这个如果我能得到答案,我会标记这个。感谢您的支持。
    【解决方案3】:

    我创建了一个基于解析器的解决方案,它输出包含键值对的字典。它可以嵌套{KeyValuePair}s 任意深度。

    这样使用:

    string data = File.ReadAllText("data.txt");
    var p = new Parser(text);
    Dictionary<string, Value> dictionary = p.Parse();
    

    值可以是字符串或字典:

    public abstract class Value { }
    
    public class StringValue : Value
    {
        public string Value { get; private set; }
        public StringValue(string value)
        {
            this.Value = value;
        }
    }
    
    public class DictionaryValue : Value
    {
        public Dictionary<string, Value> Values { get; private set; }
        public DictionaryValue()
        {
            this.Values = new Dictionary<string, Value>();
        }
    }
    

    这允许错误报告:

    public class ParseError : Exception
    {
        public ParseError(string message)
            : base(message) { }
    }
    

    解析器由两部分组成。 标记器,将输入文本转换为标记流:

    KeyValuePair, OpenBracket, KeyOrValue(Key1) , 赋值, KeyOrValue(Value1) , Next, KeyOrValue(Key2) , 赋值, KeyOrValue(Value2) , Next, KeyOrValue(Key3) , 赋值, KeyOrValue(Value3) , Next, KeyOrValue(Key4) , 赋值, KeyValuePair, OpenBracket, KeyOrValue(KeyA) , 赋值, KeyOrValue(ValueA) , Next, KeyOrValue(KeyB) , 赋值, KeyOrValue(ValueB) , Next, KeyOrValue(KeyC) , 赋值, KeyOrValue(ValueC) , Next, CloseBracket, CloseBracket, End

    然后是解析器,它将令牌流转换为字典。

    完整代码如下:

    public class Parser
    {
        private Tokenizer tk;
        public Parser(string text)
        {
            this.tk = new Tokenizer(text);
        }
        public Dictionary<string, Value> Parse()
        {
            Stack<Dictionary<string, Value>> dictionaries = new Stack<Dictionary<string, Value>>();
    
            Token t;
    
            while ((t = tk.ReadToken()) != Token.End)
            {
                switch (t)
                {
                    case Token.KeyValuePair:
                        t = tk.ReadToken();
                        if (t != Token.OpenBracket)
                            throw new ParseError("{KeyValuePair} should be followed by a '{'");
                        dictionaries.Push(new Dictionary<string, Value>());
                        break;
                    case Token.CloseBracket:
                        if (dictionaries.Count > 1)
                            dictionaries.Pop();
                        break;
                    case Token.KeyOrValue:
                        string key = tk.TokenValue;
                        t = tk.ReadToken();
                        if (t != Token.Assign)
                            throw new ParseError("Key should be followed by a '='");
                        t = tk.ReadToken();
                        if (t == Token.KeyValuePair)
                        {
                            var value = new DictionaryValue();
                            dictionaries.Peek().Add(key, value);
                            dictionaries.Push(value.Values);
                        }
                        else if (t != Token.KeyOrValue)
                            throw new ParseError("Value expected after " + key + " =");
                        else
                        {
                            string value = tk.TokenValue;
                            dictionaries.Peek().Add(key, new StringValue(value));
                            t = tk.ReadToken();
                            if (t != Token.Next)
                                throw new ParseError("{next} expected after Key value pair (" + key + " = " + value + ")");
                        }
                        break;
                    case Token.Error:
                        break;
                    default:
                        break;
                }
            }
            return dictionaries.Peek();
        }
    
        private class Tokenizer
        {
            private string _data;
            private int currentIndex = 0;
            private string tokenValue;
    
            public string TokenValue
            {
                get { return tokenValue; }
            }
    
            public Tokenizer(string data)
            {
                this._data = data;
            }
    
            public Token ReadToken()
            {
                tokenValue = string.Empty;
                if (currentIndex >= _data.Length) return Token.End;
    
                char c = _data[currentIndex];
                if (char.IsWhiteSpace(c))
                {
                    currentIndex++;
                    return ReadToken();
                }
                else if (c == '{')
                {
                    if (TryReadBracketedToken("KeyValuePair"))
                    {
                        currentIndex++;
                        return Token.KeyValuePair;
                    }
                    else if (TryReadBracketedToken("next"))
                    {
                        currentIndex++;
                        return Token.Next;
                    }
                    else
                    {
                        currentIndex++;
                        return Token.OpenBracket;
                    }
                }
                else if (c == '}')
                {
                    currentIndex++;
                    return Token.CloseBracket;
                }
                else if (c == '=')
                {
                    currentIndex++;
                    return Token.Assign;
                }
                else
                {
                    StringBuilder valueBuilder = new StringBuilder();
                    while (currentIndex < _data.Length && !char.IsWhiteSpace(c))
                    {
                        valueBuilder.Append(c);
                        currentIndex++;
                        c = _data[currentIndex];
                    }
                    tokenValue = valueBuilder.ToString();
                    return Token.KeyOrValue;
                }
            }
    
            private bool TryReadBracketedToken(string token)
            {
                bool result = _data.Length > currentIndex + token.Length + 2
                            && _data.Substring(currentIndex + 1, token.Length + 1) == token + "}";
                if (result)
                {
                    currentIndex++;
                    currentIndex += token.Length;
                }
                return result;
            }
        }
    
        private enum Token
        {
            KeyValuePair,
            Next,
            OpenBracket,
            CloseBracket,
            Assign,
            KeyOrValue,
            End,
            Error
        }
    }
    
    public abstract class Value { }
    
    public class StringValue : Value
    {
        public string Value { get; private set; }
        public StringValue(string value)
        {
            this.Value = value;
        }
    }
    
    public class DictionaryValue : Value
    {
        public Dictionary<string, Value> Values { get; private set; }
        public DictionaryValue()
        {
            this.Values = new Dictionary<string, Value>();
        }
    }
    
    public class ParseError : Exception
    {
        public ParseError(string message)
            : base(message) { }
    }
    

    【讨论】:

    • 首先非常感谢您的努力。我是 c# 的初学者,所以我无法完全理解代码。如果您希望我可以向您展示我的代码到目前为止我所做的事情。这是有效的,但由于一些循环语句,我无法将数据从控制器发送到视图
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-11
    • 1970-01-01
    • 2018-03-22
    相关资源
    最近更新 更多