如何使用.NET在文本文件中查找特定单词

时间:2010-04-08 01:19:21

标签: c# .net asp.net regex

我发送邮件(在asp.net,c#中),在文本文件(.txt)中有一个模板,如下所示

User Name :<User Name>

Address : <Address>.

我曾经使用下面的代码

替换文本文件中尖括号内的单词
StreamReader sr;
sr = File.OpenText(HttpContext.Current.Server.MapPath(txt));

copy = sr.ReadToEnd();

sr.Close(); //close the reader

copy = copy.Replace(word.ToUpper(),"#" + word.ToUpper()); //remove the word specified UC


//save new copy into existing text file

FileInfo newText = new FileInfo(HttpContext.Current.Server.MapPath(txt));

StreamWriter newCopy = newText.CreateText();
newCopy.WriteLine(copy);
newCopy.Write(newCopy.NewLine);
newCopy.Close();

现在我遇到了一个新问题,

用户将在一个角度内添加新单词,例如,他们将添加<Salary>.

在这种情况下,我必须读出并找到单词<Salary>.

换句话说,我必须找到所有用尖括号(&lt;&gt;)定位的单词。

我该怎么做?

3 个答案:

答案 0 :(得分:2)

使用正则表达式。

var matches = Regex.Matches(text, "<(.*?)>");
List<string> words = new List<string>();

for (int i = 0; i < matches.Count; i++)
{
    words.Add(matches[i].Groups[1].Value);
}

当然,这假设您已经在变量中包含了文件的文本。由于您必须阅读整个文件才能实现这一目标,因此您可以在阅读流时查找单词,但我不知道性能会有什么影响。

答案 1 :(得分:2)

拥有文件流,您可以构建类似于典型标记器的内容。

一般来说,这可以作为一个有限状态机:你需要一个枚举状态(在这种情况下可以简化为布尔值,但我会给你一般的方法,所以你可以在类似的情况下重用它任务);以及实现逻辑的功能。 C#的迭代器非常适合这个问题,所以我将在下面的代码片段中使用它们。您的函数将流作为参数,将在内部使用枚举值和char缓冲区,并逐个生成字符串。您需要在代码文件的开头附近使用它:

using System.Collections.Generic;
using System.IO;
using System.Text;

然后,在你的课堂里,这样的事情:

enum States {
    OUT,
    IN,
}
IEnumerable<string> GetStrings(TextReader reader) {
    States state=States.OUT;
    StringBuilder buffer;
    int ch;
    while((ch=reader.Read())>=0) {
        switch(state) {
            case States.OUT:
                if(ch=='<') {
                    state=States.IN;
                    buffer=new StringBuilder();
                }
                break;
            case States.IN:
                if(ch=='>') {
                    state=States.OUT;
                    yield return buffer.ToString();
                } else {
                    buffer.Append(Char.ConvertFromUtf32(ch));
                }
                break;
        }
    }
}

有限状态机模型总是具有相同的布局:while(READ_INPUT) { switch(STATE) {...}}:在开关的每个案例中,您可能正在产生输出和/或改变状态。除此之外,算法是根据状态和状态变化来定义的:对于任何给定的状态和输入组合,都有一个精确的新状态和输出组合(输出在那些不触发输出的状态下可以是“无”;以及如果没有触发状态变化,则状态可能是相同的旧状态。)

希望这有帮助。

编辑:忘了提几件事:

1)通过为文件创建StreamReader,或者如果已经在字符串上有文件,则将TextReader传递给函数。

2)这种方法的内存和时间成本是O(n),n是文件的长度。对于这类任务来说,它们似乎很合理。

答案 2 :(得分:1)

这不是答案,但评论不能这样做:

您应该将一些对象放入using块中。像这样:

using(StreamReader sr = File.OpenText(HttpContext.Current.Server.MapPath(txt)))
{
    copy = sr.ReadToEnd();
} // reader is closed by the end of the using block

//remove the word specified UC 
copy = copy.Replace(word.ToUpper(), "#" + word.ToUpper());    

//save new copy into existing text file 

FileInfo newText = new FileInfo(HttpContext.Current.Server.MapPath(txt));

using(var newCopy = newText.CreateText())
{
    newCopy.WriteLine(copy);
    newCopy.Write(newCopy.NewLine);
}

using块确保即使抛出异常也会清理资源。