Подтвердить что ты не робот

Нормализовать символы перевода строки в С#

У меня есть поток данных, который может содержать \r,\n,\r\n,\n\r или любую их комбинацию. Есть ли простой способ нормализовать данные, чтобы все они просто становились парами \r\n, чтобы сделать отображение более последовательным?

Итак, что-то, что дало бы такую ​​таблицу переводов:

\r     --> \r\n
\n     --> \r\n
\n\n   --> \r\n\r\n
\n\r   --> \r\n
\r\n   --> \r\n
\r\n\n --> \r\n\r\n
4b9b3361

Ответ 1

Я считаю, что это сделает то, что вам нужно:

using System.Text.RegularExpressions;
// ...
string normalized = Regex.Replace(originalString, @"\r\n|\n\r|\n|\r", "\r\n");

Я не уверен на 100% на точный синтаксис, и у меня нет компилятора .Net, который можно проверить. Я написал его в perl и преобразовал его в (надеюсь, правильно) С#. Единственный реальный трюк - сначала совместить "\ r\n" и "\n\r".

Чтобы применить его ко всему потоку, просто запустите на куски ввода. (Вы можете сделать это с помощью обтекателя потока, если хотите.)


Оригинальный perl:

$str =~ s/\r\n|\n\r|\n|\r/\r\n/g;

Результаты теста:

[bash$] ./test.pl
\r -> \r\n
\n -> \r\n
\n\n -> \r\n\r\n
\n\r -> \r\n
\r\n -> \r\n
\r\n\n -> \r\n\r\n

Обновление: теперь преобразует \n\r в\r\n, хотя я бы не назвал эту нормализацию.

Ответ 2

Regex поможет.. может сделать что-то примерно так.

(\ r\n |\n\n |\n\r |\r |\n) заменим на \r\n

Это регулярное выражение произвело эти результаты из таблицы (просто проверяя левую сторону), чтобы замена нормализовалась.

\r   => \r 
\n   => \n 
\n\n => \n\n 
\n\r => \n\r 
\r\n => \r\n 
\r\n => \r\n 
\n   => \n 

Ответ 3

Я с Джейми Завински на RegEx:

"Некоторые люди, столкнувшись с проблемой, думают" Я знаю, что я использую регулярные выражения ". Теперь у них есть две проблемы"

Для тех из нас, кто предпочитает читаемость:

  • Шаг 1

    Заменим\r\n на \n

    Замените\n\r на \n (если вы действительно этого хотите, некоторые плакаты, похоже, не думают)

    Заменить\r на \n

  • Шаг 2 Замените \n на Environment.NewLine или \r\n или что-то еще.

Ответ 4

Я согласен, что Regex - это ответ, однако все остальные не упоминают разделители строк Unicode. Те (и их варианты с \n) должны быть включены.

Ответ 5

Вы думаете слишком сложно. Игнорируйте каждый \r и превратите каждый \n в\r\n.

В Pseudo-С#:

char[] chunk = new char[X];
StringBuffer output = new StringBuffer();

buffer.Read(chunk);
foreach (char c in chunk)
{
   switch (c)
   {
      case '\r' : break; // ignore
      case '\n' : output.Append("\r\n");
      default   : output.Append(c);
   }
 }

EDIT:\r не является линейным терминатором, поэтому я сомневаюсь, что вы действительно хотите расширить \r до\r\n.

Ответ 6

Нормализовать разрывы, так что все они \r\n

var normalisedString =
            sourceString
            .Replace("\r\n", "\n")
            .Replace("\n\r", "\n")
            .Replace("\r", "\n")
            .Replace("\n", "\r\n");

Ответ 7

Это ответ на вопрос. Данное решение заменяет строку данной таблицей перевода. Он не использует дорогостоящую функцию регулярного выражения. Он также не использует несколько функций замены, каждый из которых индивидуально перебирает данные с несколькими проверками и т.д.

Таким образом, поиск выполняется непосредственно в 1 для цикла. Для количества попыток увеличения емкости массива результатов цикл также используется в функции Array.Copy. Это все петли. В некоторых случаях более высокий размер страницы может быть более эффективным.

public static string NormalizeNewLine(this string val)
{
    if (string.IsNullOrWhiteSpace(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' фактически не используется на базовых платформах. Кто будет использовать два типа разрывов строк подряд, чтобы указать 2 разрыва строки? Если вы хотите это знать, вам нужно сначала взглянуть, чтобы узнать, используются ли \n и\r в отдельном документе в одном документе.