如何将字符串中的所有换行序列规范化为一种类型?
我希望将它们全部用于电子邮件(MIME文档)的CRLF。理想情况下,这将包含在静态方法中,执行速度非常快,而不是使用正则表达式(因为换行符,回车符等的差异是有限的)。也许甚至有一种我忽略的BCL方法?
假设:在更多地考虑之后,我认为说CR是独立的或CRLF序列的一部分是一个安全的假设。也就是说,如果您看到CRLF,那么您就知道可以删除所有CR。否则,很难说出“/ r \ n \ n \ r”之类的行应该有多少行。
答案 0 :(得分:61)
input.Replace("\r\n", "\n").Replace("\r", "\n").Replace("\n", "\r\n")
如果输入只包含一种类型的换行符(CR或LF或CR + LF),这将有效。
答案 1 :(得分:29)
这取决于完全要求是什么。特别是,你想如何自己处理“\ r”?这应算作换行吗?作为一个例子,如何处理“a \ n \ rb”?这是一个非常奇怪的换行,一个“\ n”休息然后是一个流氓“\ r”,还是两个单独的换行符?如果“\ r”和“\ n”都可以自行换行,为什么“\ r \ n”不能被视为两个换行符?
以下是一些我怀疑合理效率的代码。
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();
}
}
答案 2 :(得分:6)
简单变体:
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");
答案 3 :(得分:4)
string nonNormalized = "\r\n\n\r";
string normalized = nonNormalized.Replace("\r", "\n").Replace("\n", "\r\n");
答案 4 :(得分:1)
Environment.NewLine;
对于非Unix平台,包含“ \ r \ n”的字符串,对于Unix平台,包含“ \ n”的字符串。
答案 5 :(得分:0)
这是一种快速的方法,我的意思是。
它不使用昂贵的正则表达式函数。 它也不使用多个替换函数,每个函数都通过多个检查,分配等单独循环数据。
因此,搜索直接在一个for
循环中完成。对于必须增加结果数组容量的次数,在Array.Copy
函数中也使用循环。这就是所有的循环。
在某些情况下,更大的页面大小可能更有效。
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);
}
我现在''n \ r'实际上并没有在基本平台上使用。但谁会连续使用两种类型的换行符来表示两个换行符?
如果您想知道这一点,那么您需要先了解一下\ n和\ r是否在同一文档中单独使用。