Dividi stringa per lunghezza
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 #?
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 .
(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();
}