Question

J'ai une valeur de chaîne dont la longueur est de 5000 + caractères, je souhaite la scinder en 76 caractères avec une nouvelle ligne à la fin de chaque 76 caractères. comment ferais-je cela en c #?

Était-ce utile?

La solution

Si vous écrivez des données Base64, essayez d'écrire

Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks);

Ceci insérera une nouvelle ligne tous les 76 caractères

Autres conseils

Si vous souhaitez que StringBuilder soit comparé aux performances d'une chaîne, le meilleur article est celui qui contient codeproject ici .

alt text

(Cela ne montre cependant pas la taille de la chaîne)

En résumé, StringBuilder n’est pas plus rapide tant qu’un seuil n’est pas atteint avec la longueur de la chaîne (ou le contactenation répété), ce qui vous tient à cœur, collez donc la concaténation de chaînes et les méthodes String habituelles.

Essayez ceci:

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

EDIT: Apparemment, c’est la méthode la plus lente de toutes celles postées jusqu’à présent. Je me demande comment cela se passe si vous pré-compilez la regex:

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

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

Aussi, comment se compare-t-il à une approche d'appariement direct?

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

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

Je me suis toujours demandé à quel point ces recherches illimitées étaient chères.

Un peu plus laid ... mais beaucoup plus rapide;) (cette version a pris 161 ticks ... Aric a pris 413)

J'ai posté mon code de test sur mon blog. http://hackersbasement.com/?p=134 (J'ai aussi trouvé que StringBuilder était beaucoup plus lent que string.Join)

http://hackersbasement.com/?p=139 < = résultats mis à jour

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

s étant votre chaîne de saisie et len la longueur de ligne souhaitée (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);
        }
    }
}

Ensuite, pour les rassembler:

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

Ou vous pouvez faire ceci:

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

Encore un .... (première fois en ralentissant, les exécutions suivantes, semblables aux temps plus rapides signalés ci-dessus)

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

Edit: J'étais curieux de voir à quelle vitesse la sous-chaîne était ...

La chaîne contient 5 000 caractères ... Je ne pense pas que la vitesse soit vraiment essentielle, à moins que vous ne fassiez cela des milliers, voire des millions de fois, en particulier lorsque le PO ne mentionnait même pas que la vitesse était importante. Optimisation prématurée?

J'utiliserais probablement la récursivité car, à mon avis, cela conduirait au code le plus simple.

Cela n’est peut-être pas correct, car je connais .NET mais pas C #.

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

principalement pour le plaisir, voici une solution différente implémentée comme méthode d'extension à chaîne: (\ r \ n est utilisé explicitement et ne supportera donc que ce format pour 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);
        }

En fin de compte, ce serait ce que je voudrais utiliser, je pense

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

en regardant AppendLine sous le réflecteur:

    <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

Pour moi, en ce qui concerne la vitesse, le faire manuellement > AppendLine

Je divise la chaîne par 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 réponse de @ M4N est très bonne, mais je pense que while statement est plus facile à comprendre que 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();
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top