c# - 在没有内存泄漏的情况下替换大字符串中的文本

标签 c# .net memory-leaks replace

我目前正在处理一个必须连续生成大约 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/

相关文章:

c# - Convert.ChangeType不接受十进制的 "1E-5"科学计数法,如何修复?

c# - 如果使用 vstest.console.exe 的一项测试失败,如何停止测试?

c# - Parallel.ForEach 在与 BlockingCollection 集成时停止

c++ - 如果引用应该保留,不会在析构函数中删除指针会导致内存泄漏吗?

c# - 识别显示器

C# 压缩和 JavaScript 解压

c# - 如何计算 WCF 服务器发送到客户端的消息流的大小

c# - 如何将字符串转换为偶校验的 7 位 ASCII?

c++ - 撤消/重做时释放内存时出现问题

c++ - Windows下GNU C/C++内存泄漏检测