在C#/.NET中强制CRLF的快速方法是什么?
如何将字符串中的所有新行序列规范化为一种类型 我正在寻找使他们所有的电子邮件(MIME文件)的目的CRLF。理想情况下,这将被包装在一个静态方法中,执行速度非常快,并且不使用正则表达式(因为换行符、回车符等的方差是有限的)。也许有一种BCL方法我忽略了 假设:在仔细考虑之后,我认为可以安全地假设CR是独立的或是CRLF序列的一部分。也就是说,如果您看到CRLF,那么您知道所有CR都可以删除。否则,很难判断像“\r\n\n\r”这样的内容应该有多少行 如果输入仅包含一种类型的换行符(CR、LF或CR+LF),则这将起作用。这取决于具体的要求。特别是,您希望如何单独处理“\r”?这算不算断线?例如,“a\n\rb”应该如何处理?是一个非常奇怪的换行符,一个“\n”换行符,然后是一个流氓“\r”,还是两个单独的换行符?如果“\r”和“\n”都可以单独作为换行符,为什么“\r\n”不应被视为两个换行符 下面是一些我认为相当有效的代码在C#/.NET中强制CRLF的快速方法是什么?,c#,.net,string,newline,C#,.net,String,Newline,如何将字符串中的所有新行序列规范化为一种类型 我正在寻找使他们所有的电子邮件(MIME文件)的目的CRLF。理想情况下,这将被包装在一个静态方法中,执行速度非常快,并且不使用正则表达式(因为换行符、回车符等的方差是有限的)。也许有一种BCL方法我忽略了 假设:在仔细考虑之后,我认为可以安全地假设CR是独立的或是CRLF序列的一部分。也就是说,如果您看到CRLF,那么您知道所有CR都可以删除。否则,很难判断像“\r\n\n\r”这样的内容应该有多少行 如果输入仅包含一种类型的换行符(CR、LF或C
using System;
using System.Text;
class LineBreaks
{
static void Main()
{
Test("a\nb");
Test("a\nb\r\nc");
Test("a\r\nb\r\nc");
Test("a\rb\nc");
Test("a\r");
Test("a\n");
Test("a\r\n");
}
static void Test(string input)
{
string normalized = NormalizeLineBreaks(input);
string debug = normalized.Replace("\r", "\\r")
.Replace("\n", "\\n");
Console.WriteLine(debug);
}
static string NormalizeLineBreaks(string input)
{
// Allow 10% as a rough guess of how much the string may grow.
// If we're wrong we'll either waste space or have extra copies -
// it will still work
StringBuilder builder = new StringBuilder((int) (input.Length * 1.1));
bool lastWasCR = false;
foreach (char c in input)
{
if (lastWasCR)
{
lastWasCR = false;
if (c == '\n')
{
continue; // Already written \r\n
}
}
switch (c)
{
case '\r':
builder.Append("\r\n");
lastWasCR = true;
break;
case '\n':
builder.Append("\r\n");
break;
default:
builder.Append(c);
break;
}
}
return builder.ToString();
}
}
public static string NormalizeNewLine(this string val)
{
if (string.IsNullOrEmpty(val))
return val;
const int page = 6;
int a = page;
int j = 0;
int len = val.Length;
char[] res = new char[len];
for (int i = 0; i < len; i++)
{
char ch = val[i];
if (ch == '\r')
{
int ni = i + 1;
if (ni < len && val[ni] == '\n')
{
res[j++] = '\r';
res[j++] = '\n';
i++;
}
else
{
if (a == page) // Ensure capacity
{
char[] nres = new char[res.Length + page];
Array.Copy(res, 0, nres, 0, res.Length);
res = nres;
a = 0;
}
res[j++] = '\r';
res[j++] = '\n';
a++;
}
}
else if (ch == '\n')
{
int ni = i + 1;
if (ni < len && val[ni] == '\r')
{
res[j++] = '\r';
res[j++] = '\n';
i++;
}
else
{
if (a == page) // Ensure capacity
{
char[] nres = new char[res.Length + page];
Array.Copy(res, 0, nres, 0, res.Length);
res = nres;
a = 0;
}
res[j++] = '\r';
res[j++] = '\n';
a++;
}
}
else
{
res[j++] = ch;
}
}
return new string(res, 0, j);
}
简单变体:
Regex.Replace(input, @"\r\n|\r|\n", "\r\n")
为了获得更好的性能:
static Regex newline_pattern = new Regex(@"\r\n|\r|\n", RegexOptions.Compiled);
[...]
newline_pattern.Replace(input, "\r\n");
我是说,这是一个快速的方法 它不使用昂贵的正则表达式函数。 它也不使用多个替换函数,每个替换函数都通过多次检查、分配等对数据进行循环 因此,直接在一个
循环中对进行搜索。对于必须增加结果数组容量的次数,在array.Copy
函数中还使用了一个循环。这就是所有的循环。
在某些情况下,较大的页面大小可能更有效
using System;
using System.Text;
class LineBreaks
{
static void Main()
{
Test("a\nb");
Test("a\nb\r\nc");
Test("a\r\nb\r\nc");
Test("a\rb\nc");
Test("a\r");
Test("a\n");
Test("a\r\n");
}
static void Test(string input)
{
string normalized = NormalizeLineBreaks(input);
string debug = normalized.Replace("\r", "\\r")
.Replace("\n", "\\n");
Console.WriteLine(debug);
}
static string NormalizeLineBreaks(string input)
{
// Allow 10% as a rough guess of how much the string may grow.
// If we're wrong we'll either waste space or have extra copies -
// it will still work
StringBuilder builder = new StringBuilder((int) (input.Length * 1.1));
bool lastWasCR = false;
foreach (char c in input)
{
if (lastWasCR)
{
lastWasCR = false;
if (c == '\n')
{
continue; // Already written \r\n
}
}
switch (c)
{
case '\r':
builder.Append("\r\n");
lastWasCR = true;
break;
case '\n':
builder.Append("\r\n");
break;
default:
builder.Append(c);
break;
}
}
return builder.ToString();
}
}
public static string NormalizeNewLine(this string val)
{
if (string.IsNullOrEmpty(val))
return val;
const int page = 6;
int a = page;
int j = 0;
int len = val.Length;
char[] res = new char[len];
for (int i = 0; i < len; i++)
{
char ch = val[i];
if (ch == '\r')
{
int ni = i + 1;
if (ni < len && val[ni] == '\n')
{
res[j++] = '\r';
res[j++] = '\n';
i++;
}
else
{
if (a == page) // Ensure capacity
{
char[] nres = new char[res.Length + page];
Array.Copy(res, 0, nres, 0, res.Length);
res = nres;
a = 0;
}
res[j++] = '\r';
res[j++] = '\n';
a++;
}
}
else if (ch == '\n')
{
int ni = i + 1;
if (ni < len && val[ni] == '\r')
{
res[j++] = '\r';
res[j++] = '\n';
i++;
}
else
{
if (a == page) // Ensure capacity
{
char[] nres = new char[res.Length + page];
Array.Copy(res, 0, nres, 0, res.Length);
res = nres;
a = 0;
}
res[j++] = '\r';
res[j++] = '\n';
a++;
}
}
else
{
res[j++] = ch;
}
}
return new string(res, 0, j);
}
公共静态字符串NormalizeNewLine(此字符串val)
{
if(string.IsNullOrEmpty(val))
返回val;
常量int page=6;
INTA=页面;
int j=0;
int len=值长度;
char[]res=新字符[len];
对于(int i=0;i
我现在知道“\n\r”实际上没有在基本平台上使用。但是谁会连续使用两种类型的换行符来表示两种换行符呢
如果您想知道这一点,则需要先看一看,以了解\n和\r两者是否在同一文档中分别使用。Environment.NewLine
对于非Unix平台,包含“\r\n”的字符串;对于Unix平台,包含“\n”的字符串。此示例生成四个换行符,而非规范化字符串包含两个换行符。确实,它提出了一个很好的问题,即何时使用序列以及何时删除(忽略)序列。非常酷;这对更随意的输入肯定有用!就我的情况而言,我选择了一个假设(做了一个编辑),但不管怎样,我还是投了赞成票。对。如果性能真的很重要,您可能希望将此解决方案与公认的解决方案进行基准测试,但前提是您已经通过探查器确定了它的重要性!我希望这会更快,因为它只需要对数据进行一次单一的传递?表现不好@是的,这是另一种选择。@JonSkeet这些“测试”很容易阅读,也很容易复制到编辑器或IDE中进行实验。不需要x-u-ms-test等等。正如我们(即我)所希望的那样。也可以通过使用最后一个替换插入BR标记在HTML页面上显示未知文本。Server.HtmlEncode(输入)。替换(“\r\n”、“\n”)。替换(“\r”、“\n”)。替换(“\n”、“
”);这将解决T4模板的问题。我在生成的输出中不断得到疯狂的返回。这是不可读的,我怀疑性能的提高能否弥补它。代码基于stringbuilder替换函数。来源:为什么要回滚编辑?不需要更多的空间,这取决于字符串的大小以及它的性能。使用String.Replace()的所有其他答案都会生成多个字符串,这些字符串可能非常庞大,并且会进行多次传递。最好的解决方案是myStr=Regex.Replace(myStr,”(?)?