Разделить строку по длине

2

У меня есть строковое значение, длина которого составляет 5000 + символов, я хочу разбить это на 76 символов с новой строкой в ​​конце каждого 76 символов. как woudld я делаю это в С#?

  • 0
    Что сказал Арик, но ты уверен, что хочешь разделить слово?
  • 0
    Написание почтового клиента?
Показать ещё 4 комментария
Теги:
split

12 ответов

15
Лучший ответ

Если вы пишете данные Base64, попробуйте написать

Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks);

Это добавит новую строку каждые 76 символов

  • 0
    Я буду проклят, так и будет. Должно быть быстро, использует небезопасный код. ;)
  • 0
    ну черт ... как мне сравнить это с остальными? ...
Показать ещё 1 комментарий
4

Сторона на этом, если вы хотите, чтобы StringBuilder в сравнении с строковой производительностью, лучшая статья - это код, который был найден здесь.

Изображение 174551

(Однако это не показывает размер строки)

В двух словах, StringBuilder работает не быстрее, пока пороговое значение не встретится с длиной строки (или повторным контактом), с которой вы хорошо себя чувствуете, поэтому придерживайтесь регулярных конкатенаций строк и методов String.

4

Немного уродливее... но намного быстрее;) (эта версия заняла 161 тик... Aric взял 413)

Я отправил свой тестовый код в свой блог. http://hackersbasement.com/?p=134 (Я также нашел StringBuilder намного медленнее, чем string.Join)

http://hackersbasement.com/?p=139 <= обновленные результаты

    string chopMe = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    Stopwatch sw = new Stopwatch();

    sw.Start();
    char[] chopMeArray = chopMe.ToCharArray();
    int totalLength = chopMe.Length;
    int partLength = 12;
    int partCount = (totalLength / partLength) + ((totalLength % partLength == 0) ? 0 : 1);
    int posIndex = 0;
    char[] part = new char[partLength];
    string[] parts = new string[partCount];
    int get = partLength;
    for (int i = 0; i < partCount; i++)
    {
        get = Math.Min(partLength, totalLength - posIndex);
        Array.Copy(chopMeArray, posIndex, part, 0, get);
        parts[i] = new string(part, 0, get);
        posIndex += partLength;
    }

    var output = string.Join("\r\n", parts) + "\r\n";
    sw.Stop();
    Console.WriteLine(sw.ElapsedTicks);
  • 0
    что вы думаете, если мой ответ?
  • 0
    Я обновил свой ответ - возможно, вы захотите снова запустить свой тест;)
Показать ещё 15 комментариев
4

Попробуйте следующее:

s = Regex.Replace(s, @"(?<=\G.{76})", "\r\n");

EDIT: По-видимому, это самый медленный метод всех опубликованных до сих пор. Интересно, как это происходит, если вы предварительно скомпилируете регулярное выражение:

Regex rx0 = new Regex(@"(?<=\G.{76})");

s = rx0.Replace(s, "\r\n"); // only time this portion

Также, как он сравнивается с методом прямого сопоставления?

Regex rx1 = new Regex(".{76}");

s = rx1.Replace(s, "$0\r\n"); // only time this portion

Я всегда задавался вопросом, насколько дороги эти безграничные взгляды.

  • 0
    +1 за выполнение одной строки кода.
  • 0
    : D One-liners: версия хайку для программистов.
Показать ещё 2 комментария
1
public static IEnumerable<string> SplitString(string s, int length)
{
    var buf = new char[length];
    using (var rdr = new StringReader(s))
    {
        int l;
        l = rdr.ReadBlock(buf, 0, length);
        while (l > 0)
        {
            yield return (new string(buf, 0, l)) + Environment.NewLine;
            l = rdr.ReadBlock(buf, 0, length);
        }
    }
}

Затем, чтобы вернуть их вместе:

string theString = GetLongString();
StringBuilder buf = new StringBuilder(theString.Length + theString.Length/76);
foreach (string s in SplitString(theString, 76) { buf.Append(s); }
string result = buf.ToString();

Или вы можете это сделать:

string InsertNewLines(string s, int interval)
{
    char[] buf = new char[s.Length + (int)Math.Ceiling(s.Length / (double)interval)];

    using (var rdr = new StringReader(s))
    {
        for (int i=0; i<buf.Length-interval; i++)
        {
            rdr.ReadBlock(buf, i, interval);
            i+=interval;
            buf[i] = '\n';
        }
        if (i < s.Length)
        {
            rdr.ReadBlock(buf, i, s.Length - i);
            buf[buf.Length - 1] = '\n';
        }
    }
    return new string(buf);
}
  • 0
    Это будет обрабатывать большие файлы лучше. Но это довольно медленно
  • 0
    Основным преимуществом является то, что это позволяет легко изменить функцию для приема простого потока. Затем вы можете передать ему что-то вроде потока файлов и, возможно, никогда не загружать всю строку в память изначально.
Показать ещё 2 комментария
1
public static string InsertNewLine(string s, int len)
{
    StringBuilder sb = new StringBuilder(s.Length + (int)(s.Length/len) + 1);
    int start = 0;
    for (start=0; start<s.Length-len; start+=len)
    {
        sb.Append(s.Substring(start, len));
        sb.Append(Environment.NewLine);
    }
    sb.Append(s.Substring(start));
    return sb.ToString();
}

где s будет вашей входной строкой и len желаемой длиной строки (76).

  • 0
    +1 за то, что это каноническое решение, и ТОЧНО то, о чем просили.
  • 0
    Лучший способ использовать разрывы строк - использовать: Environment.NewLine вместо "\ n".
Показать ещё 1 комментарий
1
string[] FixedSplit(string s, int len)
{
   List<string> output;
   while (s.Length > len)
   {
      output.Add(s.Substring(0, len) + "\n");
      s.Remove(0, len);
   }
   output.Add(s + "\n");
   return output.ToArray();
}
  • 0
    ... с условием, что если вы хотите вернуть одну строку назад, вам придется прокрутить возвращаемый массив и собрать все строки обратно вместе.
  • 0
    Как мне это сделать, так как мне нужна 1 строка назад?
Показать ещё 4 комментария
0

Я разделяю строку на 35

var tempstore ="12345678901234567890123456789012345";
for (int k = 0; k < tempstore.Length; k += 35)
{
   PMSIMTRequest.Append(tempstore.Substring(k, tempstore.Length - k > 35 ? 35 : tempstore.Length - k));
   PMSIMTRequest.Append(System.Environment.NewLine);
}
messagebox.Show(PMSIMTRequest.tostring());
0

в основном для удовольствия, здесь другое решение, реализованное как метод расширения для строки: (\ r\n, используемое явно, будет поддерживать этот формат только для новой строки);

public static string Split(this string str, int len)
        {
            char org = str.ToCharArray();
            int parts = str.Length / len + (str.Length % len == 0 ? 0 : 1);
            int stepSize = len + newline.Length;
            char[] result = new char[parts * stepSize];
            int resLen = result.Length;

            for (int i =0;i<resLen ;i+stepSize)
            {
                Array.Copy(org,i*len,result,i*stepSize);
                resLen[i++] = '\r';
                resLen[i++] = '\n';
            }
            return new string(result);
        }
0

Строка - 5000 символов... Я не думаю, что скорость действительно важна, если вы не делаете это тысячи или, может быть, даже миллионы раз, особенно когда OP даже не упоминает о скорости, которая важна. Преждевременная оптимизация?

Я бы, вероятно, использовал рекурсию, так как это, на мой взгляд, приведет к простейшему коду.

Это может быть не синтаксически корректно, как я знаю .NET, но не С#.

String ChunkString(String s, Integer chunkLength) {
    if (s.Length <= chunkLength) return s;
    return String.Concat(s.Substring(0, chunkLength), 
                         ChunkString(s.Substring(chunkLength)));
}
  • 0
    Да, мы знаем это; мы только проводим сравнительный анализ, чтобы удовлетворить наше любопытство.
0

Еще один.... (первый раз через медленные последующие прогоны, похожие на более быстрые времена, размещенные выше)

private void button1_Click(object sender, EventArgs e)
{
  string chopMe = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  Stopwatch sw = new Stopwatch();
  sw.Start();
  string result = string.Join("\r\n", ChopString(chopMe).ToArray());
  sw.Stop();
  MessageBox.Show(result + " " + sw.ToString());
}


public IEnumerable<string> ChopString(string s)
{
  int i = 0;
  while (i < s.Length)
  {
    yield return i + PARTLENGTH <= s.Length ? s.Substring(i,PARTLENGTH) :s.Substring(i) ;
    i += PARTLENGTH;
  }
}

Изменить: мне было любопытно узнать, насколько быстро подстрока была...

  • 0
    Ты делаешь доброе дело. для меня следующий тест, я сделаю их все дважды. То, как строка работает первым, будет самым медленным.
0

В конце концов, это будет то, что я буду использовать, я думаю,

    static string fredou()
    {
        string s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        int partLength = 12;

        int stringLength = s.Length;
        StringBuilder n = new StringBuilder(stringLength + (int)(stringLength / partLength) + 1);
        int chopSize = 0;
        int pos = 0;

        while (pos < stringLength)
        {
            chopSize = (pos + partLength) < stringLength ? partLength : stringLength - pos;
            n.Append(s , pos, chopSize);
            n.Append("\r\n");
            pos += chopSize;
        }

        return n.ToString();         
    }

посмотрев AppendLine под рефлектором:

    <ComVisible(False)> _
    Public Function AppendLine(ByVal value As String) As StringBuilder
        Me.Append(value)
        Return Me.Append(Environment.NewLine)
    End Function

    Public Shared ReadOnly Property NewLine As String
        Get
            Return ChrW(13) & ChrW(10)
        End Get
    End Property

Для меня скорость, сделайте это вручную > AppendLine

  • 0
    Ну, вы выиграли самый медленный (279097 тиков)
  • 0
    Я обманул ... Алан медленнее
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню