在 c# 中将大字符串拆分为较小的块

本文关键字:拆分 字符串 | 更新日期: 2023-09-27 18:31:24

我有一个用换行符分隔的大字符串。此字符串包含 100 行。我想将这些行分成小块,比如 20 块也基于换行符。

假设字符串变量是这样的,

1
号线 这是2
号线 3号线在这里
我是4号线

现在我想将这个大字符串变量分成 2 的小块。结果应该是 2 个字符串,

第 1
行 这是第 2 行


3号线在这里
,我是4号线

使用拆分功能,我没有得到预期的结果。请帮助我实现这一目标。

提前感谢,
维杰

在 c# 中将大字符串拆分为较小的块

简单的方法(在 Environment.NewLine 上拆分,然后循环和追加):

public static List<string> GetStringSegments(string originalString, int linesPerSegment)
{
    List<string> segments = new List<string>();
    string[] allLines = originalString.Split(new string[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries); 
    StringBuilder sb = new StringBuilder();
    int linesProcessed = 0;
    for (int i = 0; i < allLines.Length; i++)
    {
        sb.AppendLine(allLines[i]);
        linesProcessed++;
        if (linesProcessed == linesPerSegment
            || i == allLines.Length-1)
        {
            segments.Add(sb.ToString());
            sb.Clear();
            inesProcessed = 0;
        }
    }
    return segments;
}

上述方法效率略低,因为它需要先将字符串拆分为单独的行,从而创建不必要的字符串。1000 行的字符串将创建一个包含 1000 个字符串的数组。 如果我们只是扫描字符串并搜索'n,我们可以改进这一点:

public static List<string> GetStringSegments(string original, int linesPerSegment)
{
    List<string> segments = new List<string>();
    int startIndex = 0;
    int newLinesEncountered = 0;
    for (int i = 0; i < original.Length; i++)
    {
        if (original[i] == ''n')
        {
            newLinesEncountered++;
        }
        if (newLinesEncountered == linesPerSegment
            || i == original.Length - 1)
        {
            segments.Add(original.Substring(startIndex, (i - startIndex + 1)));
            startIndex = i + 1;
            newLinesEncountered = 0;
        }
    }
    return segments;
}
您可以使用

类似于批处理运算符的内容 http://www.make-awesome.com/2010/08/batch-or-partition-a-collection-with-linq

string s = "[YOUR DATA]";
var lines = s.Split(new[]{Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);
foreach(var batch in lines.Batch(20))
{
  foreach(batchLine in batch)
  {
    Console.Writeline(batchLine);
  }
}
static class LinqEx
{
  // from http://www.make-awesome.com/2010/08/batch-or-partition-a-collection-with-linq
  public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> collection,
                int batchSize)
  {
    List<T> nextbatch = new List<T>(batchSize);
    foreach (T item in collection)
    {
      nextbatch.Add(item);
      if (nextbatch.Count == batchSize)
      {
        yield return nextbatch;
        nextbatch = new List<T>(batchSize);
      }
    }
    if (nextbatch.Count > 0)
      yield return nextbatch;
  }
}

正如几个人提到的,使用 string.Split 会将整个字符串拆分到内存中,这可能是一个分配繁重的操作。这就是为什么我们有 TextReader 类及其后代,它们应该提供更好的内存性能,并且在逻辑上也可能更清晰:

using (var reader = new StringReader(myString))
{
    do
    {
        StringBuilder newString = null;
        StringWriter newStringWriter = null;
        if (lineCounter % 20 == 0)
        {
             newString = new StringBuilder();
             newStringWriter = new StringWriter(newString);
             newStringCollection.Add(newString);
        } 
        string line = reader.ReadLine();
        if (!string.isNullOrEmpty(line))
        {
             newStringWriter.WriteLine(line);
             lineCounter++;
        }
    }
    while (line != null)
}

我们使用StringReader来读取我们的大字符串,一次一行。相应的StringWriter将这些行写入新字符串,一次一行。每 20 行之后,我们开始一个新的StringBuilder(以及相应的StringWriter包装器)。

用换行符拆分字符串。然后在使用字符串时将字符串的数量合并/获取在一起。

string s = "Line1'nThis is line2 'nLine3 is here'nI am Line4";
string [] str = s.split(''n');
List<String> str1 = new List<String>();
for(int i=0; i<str.Length; i+=2)
{
    string ss = str[i];
    if(i+1 <str.Length)
        ss += ''n' + str[i+1];
    str1.Add(ss);
}
str = str1.ToArray();

如果在循环内检查了条件,因为可能是str的长度是奇数

var strAray = myLongString.Split(''n').ToList();
var skip=0;
var take=20;
var chunk = strAray.Skip(skip).Take(take).ToList();
While(chunk.Count >0)
{
foreach(var line in chunk)
{
// use line string
}
skip++;
chunk = strAray.Skip(skip).Take(take).ToList()
}