Domanda

Ho un valore di stringa che ha una lunghezza di oltre 5000 caratteri, voglio dividerlo in 76 caratteri con una nuova riga alla fine di ogni 76 caratteri. come posso farlo in c #?

È stato utile?

Soluzione

Se stai scrivendo dati Base64, prova a scrivere

Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks);

Questo inserirà una nuova riga ogni 76 caratteri

Altri suggerimenti

A questo proposito, se vuoi StringBuilder contro le prestazioni delle stringhe, l'articolo migliore è quello del codeproject trovato qui .

alt text

(Questo non mostra le dimensioni della stringa comunque)

In poche parole, StringBuilder non è più veloce fino a quando non viene raggiunta una soglia con la lunghezza della stringa (o ripetuta contatto), che è ben al di sotto, quindi attenersi alla concatenazione di stringhe normale e ai metodi String.

Prova questo:

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

EDIT: Apparentemente, questo è il metodo più lento di tutti quelli pubblicati finora. Mi chiedo come faccia se si precompila la regex:

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

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

Inoltre, come si confronta con un approccio di abbinamento diretto?

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

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

Mi sono sempre chiesto quanto siano costosi quei lookbehind illimitati.

Un po 'più brutto ... ma molto più veloce;) (questa versione ha preso 161 tick ... Aric's ha preso 413)

Ho pubblicato il mio codice di prova sul mio blog. http://hackersbasement.com/?p=134 (Ho anche trovato StringBuilder molto più lento di string.Join)

http://hackersbasement.com/?p=139 < = risultati aggiornati

    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);
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();
}

dove s sarebbe la stringa di input e len la lunghezza della linea desiderata (76).

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();
}
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);
        }
    }
}

Quindi per rimetterli insieme:

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();

O potresti farlo:

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);
}

Ancora una volta .... (prima volta attraverso corse lente e successive, simili ai tempi più veloci pubblicati sopra)

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;
  }
}

Modifica: ero curioso di vedere quanto fosse veloce la sottostringa ...

La stringa ha 5000 caratteri ... Non penso che la velocità sia davvero essenziale a meno che tu non lo stia facendo migliaia o forse anche milioni di volte, specialmente quando l'OP non ha nemmeno menzionato la velocità come importante. Ottimizzazione prematura?

Probabilmente userò la ricorsione in quanto, a mio avviso, porterebbe al codice più semplice.

Questo potrebbe non essere sintatticamente corretto, come so .NET ma non in C #.

String ChunkString(String s, Integer chunkLength) {
    if (s.Length <= chunkLength) return s;
    return String.Concat(s.Substring(0, chunkLength), 
                         ChunkString(s.Substring(chunkLength)));
}

principalmente per divertimento, ecco una diversa soluzione implementata come metodo di estensione per stringa: (\ r \ n usato esplicitamente, quindi supporterà quel formato solo per newline);

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);
        }

Alla fine, questo sarebbe quello che vorrei usare, penso

    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();         
    }

guardando AppendLine sotto il riflettore:

    <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

Per me, per quanto riguarda la velocità, farlo manualmente > AppendLine

Sto dividendo la stringa per 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());

La risposta di @ M4N è molto buona, ma penso che while statement sia più facile da capire rispetto a for statement.

public static string InsertNewLine(string source, int len = 76)
{
    var sb = new StringBuilder(source.Length + (int)(source.Length / len) + 1);
    var start = 0;
    while ((start + len) < source.Length)
    {
        sb.Append(source.Substring(start, len));
        sb.Append(Environment.NewLine);
        start += len;
    }
    sb.Append(source.Substring(start));
    return sb.ToString();
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top