55

文字列内のすべての改行シーケンスを1つのタイプにどのように正規化しますか?

電子メール(MIMEドキュメント)の目的で、それらをすべてCRLFにすることを目指しています。理想的には、これは静的メソッドにラップされ、非常に高速に実行され、正規表現を使用しません(改行、キャリッジリターンなどの分散が制限されているため)。おそらく、私が見落としていたBCLメソッドさえありますか?

仮定:これについてもう少し考えてみると、CRはスタンドアロンまたはCRLFシーケンスの一部であると言っても差し支えないと思います。つまり、CRLFが表示されている場合は、すべてのCRを削除できることがわかります。そうしないと、「\ r \ n \ n\r」のようなものから何行出てくるかを判断するのが困難になります。

4

6 に答える 6

76
input.Replace("\r\n", "\n").Replace("\r", "\n").Replace("\n", "\r\n")

これは、入力に 1 種類の改行 (CR、LF、または CR+LF) しか含まれていない場合に機能します。

于 2009-05-08T19:32:53.173 に答える
32

それは、要件が何であるかによって異なります。特に、"\r" を単独でどのように処理しますか? それは改行として数えるべきですか?例として、「a\n\rb」はどのように扱われるべきですか? それは 1 つの非常に奇妙な改行、1 つの "\n" 改行とその後の不正な "\r"、または 2 つの別個の改行ですか? 「\r」と「\n」の両方が単独で改行できる場合、「\r\n」を 2 つの改行として扱わないのはなぜですか?

ここに、かなり効率的だと思われるコードをいくつか示します。

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();
    }
}
于 2009-05-08T19:38:04.987 に答える
9

簡単なバリアント:

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");
于 2015-05-20T15:53:13.800 に答える
4
string nonNormalized = "\r\n\n\r";

string normalized = nonNormalized.Replace("\r", "\n").Replace("\n", "\r\n");
于 2009-05-08T19:28:13.700 に答える