我发送邮件(在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;)定位的单词。
我该怎么做?
答案 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
块确保即使抛出异常也会清理资源。