我目前正在处理一个必须连续生成大约 16000 封电子邮件(新闻通讯)的批处理。
无论是否是垃圾邮件,我的问题是如何生成这些电子邮件。
消息中的某些字段必须替换为自定义值(当天的日期、用户名称等)。
出于某些截止日期和代码可重用性的原因,我的模板是一个 HTML 文件,其中包含一些“_FIELDNAME”字段,可以通过正则表达式轻松发现这些字段:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
...
<body>
<p>Hi _NAME, _DATE newsletter.</p>
</body>
...
该文件大约有 1000 行,因此加载时是一个相当大的字符串。
首先,我在字符串中加载一次 HTML 文件模板:
string template = File.ReadAllText(@"Template/newsletter.html");
替换函数如下所示:
return new StringBuilder(template)
.Replace("_DATE", profileConfig.SelectedMonth.ToString("MMMM yyyy"))
.Replace("_NAME", profileConfig.Name)
.ToString();
问题在于每次迭代时内存消耗都会略有增加。 1000次迭代大约有50MB,这是由于我的替换功能(我尝试注释它,内存泄漏消失了)。
如何在 16000 次迭代中替换模板中的许多字段 (~50) 而不会导致内存溢出? 我尝试了一些方法,例如使用正则表达式(但它使用字符串)或临时文件,但两者都不令我满意。
预先感谢您的帮助。
最佳答案
如果您可以将 _DATE
、_NAME
等替换为 {0}
、{1}
等等,你可以尝试 string.Format()
模板将变成:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
...
<body>
<p>Hi {0}, {1} newsletter.</p>
</body>
...
代码如下所示:
return string.Format(template,
profileConfig.SelectedMonth.ToString("MMMM yyyy"),
profileConfig.Name
);
您实际上根本不需要通过StringBuilder
。如果您使用 File.ReadAllLines()
并且仅交换包含标记的行中的值,您将大大提高速度(并且可能会提高资源使用率)。
更新为了强制使用string.Format(string format, params object[] args)
重载,您可能必须将所有参数放入收藏。
下面的内容应该可以让这个解决方案适合您(我测试了多达 1000 个参数,它的工作速度而且都非常快)。
List<string> tokenValues = new List<string>
{
profileConfig.SelectedMonth.ToString("MMMM yyyy"),
profileConfig.Name,
<follow with your other values>
};
return string.Format(template, tokenValues.ToArray()); //.ToArray() is mandatory
关于c# - 在没有内存泄漏的情况下替换大字符串中的文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11741050/