1

请耐心等待,因为我对编程本身和 C# winforms 非常陌生。

我有一个AAA.txt文件,我让它在组合框中显示为“AAA”。我的主要目的是允许用户从下拉组合中选择 AAA,然后单击搜索。在点击事件上,该函数应该逐行读取文本文件的内容,然后查找这些词(例如你好)或短语(例如早上好)是否出现在我所有的 20 个 XML 文件的<description></description>子节点中。如果这些单词/短语确实出现在某些<description></description>子节点中,那么整个<item></item>父节点的数据将作为结果出现。

AAA.txt:

hello
good morning
great
bye

我的功能:

private void searchComByKeywords()
{ 
    string[] fileEntries = Directory.GetFiles(sourceDir);
    foreach (string fileName in fileEntries)
    {
        XmlDocument xmlDoc = new XmlDocument();
        string docPath = fileName;
        xmlDoc.Load(docPath);
        XmlNodeList nodeList = xmlDoc.GetElementsByTagName("item");

        foreach (XmlNode node in nodeList)
        {
            XmlElement itemElement = (XmlElement)node;
            string itemDescription = itemElement.GetElementsByTagName("description")[0].InnerText;

            if (itemDescription.ToLower().Contains(comboTemplates.SelectedItem.ToString()))
            {
                string itemTitle = itemElement.GetElementsByTagName("title")[0].InnerText;
                string itemDate = itemElement.GetElementsByTagName("pubDate")[0].InnerText;
                string itemAuthor = itemElement.GetElementsByTagName("author")[0].InnerText;

                richComByTemplate.AppendText("Author: " + itemAuthor + "\nDate: " + itemDate + "\nTitle: " + itemTitle + "\nDescription: " + itemDescription + "\n\n--------\n\n");
            }
        }
    }
}

我知道有些人可能会告诉我使用 LINQ-to-XML,但这不是我现在关心的问题。我知道这条线if (itemDescription.ToLower().Contains(comboTemplates.SelectedItem.ToString()))没有做我想要的(它会搜索单词“AAA”而不是查看选定的 AAA 文本文件)。我可以知道如何正确编写此行以阅读所选文本文件中出现的单词/短语吗?

谢谢你。

4

1 回答 1

2

静态System.IO.File类有一个ReadAllLines将文本文件的所有行读入数组的方法。

string[] words = File.ReadAllLines(filepath);

如果组合只包含文件名,您可能需要先用目录名补充它

string dir = @"C:\MyDataPath";
string filename = comboTemplates.SelectedItem.ToString();
string filepath = Path.Combine(dir, filename);

然后把这些词放到一个HashSet<string>

var wordSet = new HashSet<string>(words);

然后使用正则表达式将您的描述拆分为单个单词

var descrWords = 
    new HashSet<string>(
        Regex.Matches(itemDescription.ToLower(), @"\w+")
        .Cast<Match>()
        .Select(m => m.Value)
    );
descrWords.UnionWith(wordSet);
if (descrWords.Count > 0) {
    // Your description contains at least one of the words
}

您可以通过许多不同的方式进行比较。例如通过使用 LINQ

if (words.Union(
    Regex.Matches(itemDescription.ToLower(), @"\w+")
        .Cast<Match>()
        .Select(m => m.Value)
    ).Any())
{
    ...
}

注意:只看一个字符串是否包含一个单词是不够的

s.Contains("great")

因为它也会找到像“伟大”这样的词的一部分。


如果您还需要查找短语,则上述方法不起作用。您需要将 Regex 搜索与循环或 LINQ 语句结合起来。让我们使用类型的正则表达式

\bWordOrPhrase\b

\b匹配单词边界。为了确保不会在正则表达式中引入一些特殊的正则表达式字符,我们需要对单词或短语进行转义。

bool found = Regex.IsMatch(description, @"\b" + Regex.Escape(wordOrPhrase) + @"\b");

最后,我们必须对列表中的所有单词和短语进行此测试。让我们把所有东西放在一起:

string dir = @"C:\MyDataPath";
string filename = comboTemplates.SelectedItem.ToString();
string filepath = Path.Combine(dir, filename);

string[] words = File.ReadAllLines(filepath);

然后测试你的描述

string itemDescription = itemElement.GetElementsByTagName("description")[0].InnerText;
if (words.Any(
    wordOrPhrase =>
    Regex.IsMatch(itemDescription,
                  @"\b" + Regex.Escape(wordOrPhrase) + @"\b",
                  RegexOptions.IgnoreCase)))
{
    ...
}
于 2012-08-19T22:42:28.117 回答