C#以递归方式解析一些文件并打印一些信息 [英] C# recursively parse through some files and print some info

查看:57
本文介绍了C#以递归方式解析一些文件并打印一些信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Hello CodeProject社区,



我正在使用一个工具来解析一些文件以搜索其他文件...更具体一点,解析一个.c找到.h文件的文件,之后,为每个.h文件解析它们并提取它们的依赖关系,直到它们找到一个空标题。



问:它看起来如何我试图解析的结构并得到我想要的信息?



A:



请看这里



问:你有什么,直到现在?



答:嗯,我有很少的功能可以很好地获取.C文件和第一轮.h文件,包含的文件。 C文件。我的问题是,当我想在Excel文件中打印它们时,我想将它们打印成组,例如



Hello CodeProject community,

I am working to a tool which parse through some files to search other files ... To be more specific, parse a .c file to find .h files and after that, for each of .h files parse them and extract their dependencies till they hit an empty header.

Q: How it looks the structure i'm trying to parse through and get the informations i want ?

A:

See here

Q: What you have till now ?

A: Well, I have few functions which do a great job for getting the .C file and the first round of .h files, those contained by .C files. My problem is when i want to print them in a Excel File, i want to print them in groups like

File.C-->Header.H --> Header1.H - > all dependecies of Header1.H like the above example
                    -->2ndHeader.H --> Header2.H ->all dependecies of Header2.H like the above example
                                   --> Header3.H ->all dependecies of Header3.H like the above example





问:是的,但是到目前为止你还有什么输出?

答:我有以下方案作为输出,我将在您尝试过什么?中发布代码。部分。





作为输出目前,我有以下.txt:





Q: Yeah, but what you have till now as output ?
A: I have the following scheme as output, i will post the code in "WHAT have you tried?" section.


As output for the moment i have the following .txt :

File Header1.h depends of following files : 
----> Header2.h with the following path: 
				 -----> Their location
----> Header3.h with the following path: 
				 -----> Their location
----> Header4.h with the following path: 
				 -----> Their location
----> Completed dependencies of Header1.h


File Header2.h depends of following files : 

 ----> Header5.h with the following path: 
				 -----> Their location
----> Header6.h with the following path: 
				 -----> Their location
----> Completed dependencies of Header2.h



File Header3.h depends of following files : 
----> Header2.h with the following path: 
				 -----> Their location
----> Header4.h with the following path: 
				 -----> Their location
----> Completed dependencies of Header3.h



File Header4.h depends of following files : 
----> Header7.h with the following path: 
				 -----> Their location
----> Header8.h with the following path: 
				 -----> Their location
----> Header9.h with the following path: 
				 -----> Their location
----> Header10.h with the following path: 
				 -----> Their location
----> Header11.h with the following path: 
				 -----> Their location
----> Completed dependencies of Header4.h



File Header5.h depends of following files : 
----> Completed dependencies of Header5.h



File Header6.h depends of following files : 
----> Header12.h with the following path: 
				 -----> Their location
----> Completed dependencies of Header6.h



File Header7.h depends of following files : 
----> Completed dependencies of Header7.h



File Header8.h depends of following files : 
----> Completed dependencies of Header8.h



File Header9.h depends of following files : 
----> Completed dependencies of Header9.h



File Header10.h depends of following files : 
----> Completed dependencies of Header10.h



File Header11.h depends of following files : 
----> Completed dependencies of Header11.h



File Header12.h depends of following files : 
----> Header13.h with the following path: 
				 -----> Their location
----> Completed dependencies of Header12.h



File Header13.h depends of following files : 
----> Completed dependencies of Header13.h







问:你想要什么输出?

答:以下.txt:






Q: What output you desire ?
A: The following .txt:

File Header1.h depends of following files : 
----> Header2.h with the following path: 
				 -----> Their location
				 
				File Header2.h depends of following files : 

				----> Header5.h with the following path: 
				-----> Their location
				 
						File Header5.h depends of following files : 
						----> Completed dependencies of Header5.h
					
				----> Header6.h with the following path: 
				-----> Their location
				 
						File Header6.h depends of following files : 
				
						----> Header12.h with the following path: 
						-----> Their location
						----> Completed dependencies of Header6.h
						
							File Header12.h depends of following files : 
							
							----> Header13.h with the following path: 
							-----> Their location
							----> Completed dependencies of Header12.h

								File Header13.h depends of following files : 
								----> Completed dependencies of Header13.h
								
								
				 
				----> Completed dependencies of Header2.h
					
					
----> Header3.h with the following path: 
				 -----> Their location
				 
					File Header3.h depends of following files : 
					
					----> Header2.h with the following path: 
					-----> Their location
					
					----> Header4.h with the following path: 
					-----> Their location
					
				----> Completed dependencies of Header3.h

----> Header4.h with the following path: 
				 -----> Their location
				 
				File Header4.h depends of following files : 
				 
				----> Header7.h with the following path: 
				-----> Their location
				
					File Header7.h depends of following files : 
					----> Completed dependencies of Header7.h

				----> Header8.h with the following path: 
				-----> Their location
				
					File Header8.h depends of following files : 
					----> Completed dependencies of Header8.h

				----> Header9.h with the following path: 
				-----> Their location
				
					File Header9.h depends of following files : 
					----> Completed dependencies of Header9.h

				----> Header10.h with the following path: 
				-----> Their location
					
					File Header10.h depends of following files : 
					----> Completed dependencies of Header10.h

				----> Header11.h with the following path: 
				-----> Their location
				
					File Header11.h depends of following files : 
					----> Completed dependencies of Header11.h
				
				----> Completed dependencies of Header4.h
				 
----> Completed dependencies of Header1.h





我需要修改我的代码以获得第二个输出?



我尝试了什么:





WHAT i need to modify to my code to get the SECOND OUTPUT ?

What I have tried:

public static void _searchHofHeaders(FileInfo fisierH, string path, List<FileInfo> _listOfChead)
{
    List<FileInfo> _tempListOfCheaders = _listOfChead;
    if (fisierH != null)
    {
        StreamReader _file;
        _file = new StreamReader(fisierH.FullName);
        string line = null;
        try
        {
            if (_HeaderFilesToIgnore.Contains(fisierH.Name) != true)
            {
                _HeaderFilesToIgnore.Add(fisierH.Name);

                while ((line = _file.ReadLine()) != null)
                {
                    String sourcestring = line;
                    int flag = -1;

                    if ((line.StartsWith("/*") == true && line.EndsWith("*/") != true) || line.StartsWith("//") == true
                    || (line.StartsWith("/*") == true && line.EndsWith("*/") == true) || line.Contains("#include") != true)
                    {
                        flag = 1;

                    }
                    else
                    {

                        string[] _LineContent;

                        if (line.StartsWith("#include") != true)
                        {
                            if ((line.Contains("#include") == true && line.Contains("/*") == true && line.Contains("*/") == true && line.Contains("//") == true) ||
                            (line.Contains("#include") == true && line.Contains("//") == true) || (line.Contains("#include") == true && line.Contains("/*") == true && line.Contains("*/") == true)
                            || (line.Contains("#include") == true && line.Contains("/*") != true && line.Contains("*/") == true))
                            {
                                _LineContent = line.Split(new string[] { "#include" }, StringSplitOptions.RemoveEmptyEntries);

                                for (int _i = 0; _i < _LineContent.Length; _i++)
                                {
                                    if (_i == 0)
                                    {
                                        if ((_LineContent[_i].Contains("/*") == true && _LineContent[_i].Contains("*/") != true && _LineContent[_i].Contains(".h") == true) || (_LineContent[_i].Contains("//") == true && _LineContent[_i].Contains(".h") == true)
                                        || (_LineContent[_i].Contains("/*") == true && _LineContent[_i].Contains("*/") != true) || (_LineContent[_i].Contains("//") == true && _LineContent.Contains(".h") != true))
                                        flag = 1;
                                    }

                                else
                                    if (_i != 0)
                                    {
                                        if ((_LineContent[_i].Contains("/*") == true && _LineContent[_i].Contains("*/") != true && _LineContent[_i].Contains(".h") == true) || (_LineContent[_i].Contains("//") == true && _LineContent[_i].Contains(".h") == true)
                                        || (_LineContent[_i].Contains("/*") == true && _LineContent[_i].Contains("*/") != true) || (_LineContent[_i].Contains("//") == true && _LineContent.Contains(".h") != true))
                                            flag = 1;
                                    }

                                }
                            }
                        }
                    }

                    if ((line.StartsWith("*/") == true))
                    {
                        flag = 2;
                    }

                    if(flag!=1)
                        {



                                    Regex re = new Regex(@"[A-Za-z0-9\-_]+.h", RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline);
                                    MatchCollection mc = re.Matches(sourcestring);
                                    int mIdx = 0;

                                    foreach (Match m in mc)
                                    {
                                        for (int gIdx = 0; gIdx < m.Groups.Count; gIdx++)
                                        {
                                            int flag_h = 0;
                                            int flag_h1 = 0;
                                            string nume_fisier = m.Groups[gIdx].Value;

                                            if (_headers_to_search.Count != 0)
                                            {
                                                foreach (FileInfo _hToS in _headers_to_search.ToList())
                                                {
                                                    if (nume_fisier.Equals(_hToS.Name) == true)
                                                    {
                                                        flag_h = 1;
                                                    }
                                                }
                                                foreach (FileInfo _hToSfromH in _listOfChead.ToList())
                                                {
                                                    if (nume_fisier.Equals(_hToSfromH.Name) == true)
                                                    {
                                                        flag_h1 = 1;
                                                    }
                                                }

                                                if (flag_h == 1)
                                                {
                                                    foreach (FileInfo _hToS2 in _headers_to_search.ToList())
                                                    {
                                                        if (nume_fisier.Equals(_hToS2.Name) == true)
                                                        {
                                                            _headers_list.Add(_hToS2);
                                                        }
                                                    }
                                                }
                                                else
                                                {
                                                    if (flag_h1 == 1 && flag_h != 1)
                                                    {
                                                        foreach (FileInfo _hToSfromH1 in _listOfChead.ToList())
                                                        {
                                                            if (nume_fisier.Equals(_hToSfromH1.Name) == true)
                                                            {
                                                                _headers_list.Add(_hToSfromH1);
                                                            }
                                                        }
                                                    }

                                                    else
                                                        if (flag_h1 != 1 && flag_h != 1)
                                                        {
                                                            string _temppath_of_H = _searchFunction(nume_fisier, path);

                                                            if (_temppath_of_H != null)
                                                            {
                                                                FileInfo fisier_h = new FileInfo(_temppath_of_H);
                                                                if (fisier_h != null)
                                                                {
                                                                    _headers_list.Add(fisier_h);
                                                                    _headers_to_search.Add(fisier_h);
                                                                }
                                                            }
                                                        }
                                                }

                                            }
                                            else
                                                if (_headers_to_search.Count == 0)
                                                {

                                                    string _temppath_of_H = _searchFunction(nume_fisier, path);

                                                    if (_temppath_of_H != null)
                                                    {
                                                        FileInfo _fisier_h = new FileInfo(_temppath_of_H);
                                                        if (_fisier_h != null)
                                                        {
                                                            _headers_list.Add(_fisier_h);
                                                            _headers_to_search.Add(_fisier_h);
                                                        }
                                                    }
                                                }
                                        }
                                    }
                                mIdx++;

                        }
                }
            }
        }

        catch (Exception ex)
        { }

        //List<FileInfo> _headers_To_Search = _headers_list.DistinctBy(x => x.Name).ToList();

        _headers_to_search = _headers_to_search.DistinctBy(x => x.Name).ToList();
        _headers_list = _headers_list.DistinctBy(x => x.Name).ToList();

        if (_hFiles_Headers.ContainsKey(fisierH.Name) != true)
        {
            _hFiles_Headers.Add(fisierH.Name, _headers_list);
        }
        _headers_list = new List<FileInfo>();
        _file.Close();

        _HeaderFilesToIgnore = _HeaderFilesToIgnore.Distinct().ToList();


       foreach (FileInfo fisH in _headers_to_search.ToList())
       {
            try
            {
                if (_HeaderFilesToIgnore.Contains(fisH.Name) != true)
                {

                    _searchHofHeaders(fisH, path,_tempListOfCheaders);
                }
            }
            catch (Exception ex)
            {
                break;
            }

        }



    }
}







此代码仅适用于该程序的这一部分。搜索功能与我必须做的事情无关。




This code is only for this part of the program. The search function is irelevant for what i have to do.

推荐答案

我要做的第一件事是从正在解析的文件中删除所有注释。这将清理并简化用于查找包含语句的代码。这是一个应该这样做的方法(只有有限的测试,但它会让你开始)。调用此方法后,您所要做的就是查找 StartWith(#include)的行。建立你需要的递归方法应该是孩子的玩法。



The very first thing I would do is remove all of the comments from the file(s) being parsed. This would clean up and simplify the code you use to look for include statements. Here's a method that should do that (only limited testing, but it'll get you started). After calling this method, all you have to do is look for lines that StartWith("#include "). Building the recursive method you need should be child's play at this point.

public void StripComments(ref List<string> lines)
{
    // remove double-slash comments
    for (int i = lines.Count-1; i >= 0; i--)
    {
        string line = lines[i].Trim();
        if (!string.IsNullOrEmpty(line))
        {
            int pos = line.IndexOf("//");
            if (pos >= 0)
            {
                line = (pos == 0) ? string.Empty : line.Substring(pos);
            }
            lines[i] = line;
        }
    }

    // remove slash-star comments

    // create one big line
    string allLines = string.Empty;
    for (int i = 0; i < lines.Count; i++)
    {
        allLines = string.Concat(allLines, lines[i]);
    }
    allLines = allLines.Trim();

    // determine if the big line starts with a slash-star
    string[] seps = new string[]{"/*"};
    bool startsWithSlashStar = allLines.StartsWith(seps[0]);

    // split the string on the slash-star
    string[] parts = allLines.Split(seps, StringSplitOptions.None);

    // Iterate the parts and remove everything that's part of a comment. This 
    // should account for nested comments as well.
    for (int i = 0; i < parts.Length; i++)
    {
        string part = parts[i];
        int pos = part.LastIndexOf("*/");
        if (pos >= 0)
        {
            part = part.Substring(pos+2);
        }
        else
        {
            if (i == 0)
            {
                if (startsWithSlashStar)
                {
                    part = string.Empty;
                }
            }
            else
            {
                part = string.Empty;
            }
        }
        parts[i] = part;
    }

    // put it all back together into one big line
    allLines = string.Empty;
    for (int i = 0; i < parts.Length; i++)
    {
        allLines = string.Concat(allLines, parts[i]);
    }
    // split the big line of semi colons, and trim off the whitespace for each line
    parts = allLines.Split(';');
    for (int i = 0; i < parts.Length; i++)
    {
        parts[i] = parts[i].Trim();
    }

    // and put the parts back into the original lines list
    lines.Clear();
    lines.AddRange(parts);
}





Caveat - Using a recursive method could cause issues in the event you’re parsing a large project coupled with the fact that you’ve got to load every file into RAM and potentially high number of lines as you iterate found includes. You may encounter stack overflow exceptions.



It may be a good idea to modify the method above to also only add the include statements back to the original lines string list. This would significantly reduce memory consumption as you recurse the files. Simply do this at the end of the method I posted.





Caveat - Using a recursive method could cause issues in the event you're parsing a large project coupled with the fact that you've got to load every file into RAM and potentially high number of lines as you iterate found includes. You may encounter stack overflow exceptions.

It may be a good idea to modify the method above to also only add the include statements back to the original lines string list. This would significantly reduce memory consumption as you recurse the files. Simply do this at the end of the method I posted.

// if you just want the includes
var includes = parts.Where(x=>x.ToLower().StartsWith("#include "));
lines.Clear();
lines.AddRange(includes);


Try this in Visual Studio



Project Settings -> Configuration Properties -> C/C++ -> Advanced -> Show Includes



I think that will generate the hierarchy tree.
Try this in Visual Studio

Project Settings -> Configuration Properties -> C/C++ -> Advanced -> Show Includes

I think that will generate the hierarchy tree.


这篇关于C#以递归方式解析一些文件并打印一些信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆