【问题标题】:How to extract an unknown amount of text from a file如何从文件中提取未知数量的文本
【发布时间】:2013-12-10 20:53:47
【问题描述】:

这种类型与question I had earlier about a regex to search for a method containing a particular string 相关联,有人建议我使用这个名为 Roslyn 的 MS 工具,但自 2012 年问世以来,它不适用于 VS2010。

所以我正在编写这个小实用程序来保留我的解决方案中包含特定方法声明的每个文件的列表(例如 25k 文件中的 3k 重载此方法)。然后我只想将该文件列表过滤为仅在方法主体内包含+= 的文件。

static void DirSearch(string dir)
{
    string[] files = Directory.GetFiles(dir, "*.*", SearchOption.AllDirectories);

    foreach (var file in files)
    {
        var contents = File.ReadAllText(file);
        if (contents.Contains("void DetachEvents()"))
        {
            //IF DetachEvents CONTAINS += THEN...
                WriteToFile(file);
        }                
     }
}

此方法遍历所有文件夹并将文件名写入文本文件(如果它包含关键方法),但我不知道如何仅提取方法主体中的任何内容,因为它重载了该方法的所有 3K 实例不一样。

最好的方法是获取方法名称的索引,然后是每个 {} 的索引,直到遇到下一个访问器修饰符(表示我已经到了 DetachEvents 的末尾) ?然后我可以在indexOfMethodindexOfEndMethod 之间搜索+=

但这听起来真的很草率,我希望有人可能有更好的主意?

【问题讨论】:

  • @P.Brian.Mackey 我不确定你的意思。我不打算让我的工具修改任何代码,只是告诉我哪些有错误。所以,它只是读取它们的内容,如果它们有明显的数据,则将文件名写入本地文件,让我回去手动更改。我不希望错误数据的数量惊人,但我不想手动检查 3K 文件;)
  • 你的代码库中真的有 3,000 个相同方法的不同重载吗?
  • @acfrancis 在我的帖子中快速运行代码而不进行任何“过滤”会产生一个包含大约 2.9k 条目的文本文件。它们实际上并没有从一个公共接口重载方法,但它们只是具有相同的方法签名(private void DetachEvents()),并且顾名思义,将事件从其上的每个控件中分离出来。与重载不完全相同,但足够接近,为了简单起见,我只是这么称呼它。
  • 对,我想你可以从方法签名中读取文件,计算打开和关闭花括号,直到它们平衡(这可能是方法的结尾),同时寻找 +=时间。这并不准确,因为您可能会计算字符串或 cmets 中的内容,但应该非常接近。
  • += 可以在方法主体中的任何位置,或者您可以缩小您正在寻找的语法位吗?

标签: c# winforms .net-3.5


【解决方案1】:

您必须在代码中执行此操作吗?这是识别问题方法的一次性实用程序吗?为什么不使用Notepad++ 之类的东西,它是Find in Files 功能。你可以很容易地过滤你的发现,甚至应用正则表达式(我认为)。您可以从那里复制包含文件名(即someclassfile.cs)的结果并从那里获取列表。

【讨论】:

  • 您说得对,因为这是一次性使用的工具。好吧,我想将来人们可能会错误地分配+= 而不是-=,但是,我能做些什么呢。我尝试使用 Visual Studios 中内置的正则表达式搜索来搜索我的整个解决方案以查找一些不同的内容(请参阅我在帖子顶部链接的 SO 问题),并且其他一些人表示很难创建一个可以找到问题的每个实例的正则表达式,因为每个方法都会删除不同数量的事件处理程序。另外,我无法想象尝试在 N++ 中打开 28K 文件进行搜索。
  • 评论长度限制!!我对任何解决方案持开放态度,因此,如果您知道一种方法,我可以使用 N++ 的搜索轻松解析这些不正确方法主体的列表,我会全力以赴
【解决方案2】:

我写了这个非常草率的winform,它允许用户在文件夹中输入代码库、方法名称和他们正在寻找的公然文本。然后它遍历目录中的每个文件,并在包含文件所有文本的字符串上调用此方法。如果存在用户输入的恶意数据,则返回true,然后调用此方法的方法会将其添加到列表中。无论如何,这是主要代码:

    private bool ContainsFlag(string contents)
    {
        int indexOfMethodDec = contents.IndexOf(_method);
        int indexOfNextPublicMethod = contents.IndexOf("public", indexOfMethodDec);
        if (indexOfNextPublicMethod == -1)
            indexOfNextPublicMethod = int.MaxValue;

        int indexOfNextPrivateMethod = contents.IndexOf("private", indexOfMethodDec);
        if (indexOfNextPrivateMethod == -1)
            indexOfNextPrivateMethod = int.MaxValue;

        int indexOfNextProtectedMethod = contents.IndexOf("protected", indexOfMethodDec);
        if (indexOfNextProtectedMethod == -1)
            indexOfNextProtectedMethod = int.MaxValue;

        int[] indeces = new int[3]{indexOfNextPrivateMethod,
                                   indexOfNextProtectedMethod,
                                   indexOfNextPublicMethod};

        int closestToMethod = indeces.Min();
        if (closestToMethod.Equals(Int32.MaxValue))
            return false; //This should probably do something different.. This condition is true if the method you're reading is the last method in the class, basically

       if (closestToMethod - indexOfMethodDec < 0)
            return false;

        string methodBody = contents.Substring(indexOfMethodDec, closestToMethod - indexOfMethodDec);
        if (methodBody.Contains(_flag))
            return true;
        return false;
    }

有很多改进的余地,这主要是一个概念验证的东西,每年可能会在内部使用两次。但就我的目的而言,它奏效了。如果有人需要,应该是更复杂的东西的一个很好的起点。

【讨论】:

    猜你喜欢
    • 2013-11-09
    • 2020-07-07
    • 2018-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-01
    • 2015-08-01
    相关资源
    最近更新 更多