2

我从 TCP 侦听器接受了一个大字符串,格式如下

“1,7620257787,0123456789,99,0922337203,9223372036,32.5455,87,12.7857,1 / 1 / 2012,9223372036:1,7620257787,0123456789,99,0922337203,9223372036,32.5455,87,12.7857:2012/2/1 ,234234234:3,7620257787,01234343456789,99,0922337203,9223372036,32.5455,87,12.7857,1 / 1 / 2012,9223372036:34,76202343457787,012434343456789,93339,34340922337203,9223372036,32.5455,87,12.7857,1 / 1 /2012,9223372036”

您可以看到这是一个 : 分隔的字符串,其中包含以逗号分隔的字段的记录。

我正在寻找将字符串拆分为给定数量的块的最佳(最快)方法,并注意一个块应包含完整记录(字符串最多':')

或其他说法,不应该有任何不以以下结尾的块:

例如 20 MB 字符串到 4 个 5 MB 的块,每个块都有正确的记录(因此每个块的大小可能不完全是 5 MB,但非常接近它,所有 4 个块的总和将是 20 MB)

我希望你能理解我的问题(抱歉英语不好)

我喜欢下面的链接,但是在拆分时它并没有处理完整的记录,也不知道这是否是最好和最快的方法。

按长度变量将字符串拆分为更小的字符串

4

5 回答 5

3

我不知道“大字符串”有多大,但最初我会尝试使用String.Split方法。

于 2012-07-09T11:27:39.937 回答
1

这个想法是将数据的长度划分为所需的块数,然后向后看以搜索当前块中的最后一个 sep。

    private string[] splitToBlocks(string data, int numBlocks, char sep)
    {
        // We return an array of the request length
        if (numBlocks <= 1 || data.Length == 0)
        {
            return new string [] { data };
        }

        string[] result = new string[numBlocks];

        // The optimal size of each block
        int blockLen = (data.Length / numBlocks);

        int idx = 0; int pos = 0; int lastSepPos = blockLen;
        while (idx < numBlocks)
        {
            // Search backwards for the first sep starting from the lastSepPos
            char c = data[lastSepPos];
            while (c != sep) { lastSepPos--; c = data[lastSepPos]; }

            // Get the block data in the result array
            result[idx] = data.Substring(pos, (lastSepPos + 1) - pos);

            // Reposition for then next block
            idx++;
            pos = lastSepPos + 1;

            if(idx == numBlocks-1)
                lastSepPos = data.Length - 1;
            else
                lastSepPos = blockLen * (idx + 1);
        }
        return result;
    }

请测试一下。我还没有完全测试边缘情况。

于 2012-07-09T11:57:34.323 回答
1

好的,我建议你分两个步骤:

  1. 将字符串拆分成块(见下文)
  2. 检查块的完整性

在 linq 的帮助下将字符串拆分为块(linq 扩展方法取自Split a collection into `n` parts with LINQ?):

string tcpstring = "chunk1 : chunck2 : chunk3: chunk4 : chunck5 : chunk6";
int numOfChunks = 4;

var chunks = (from string z in (tcpstring.Split(':').AsEnumerable()) select z).Split(numOfChunks);

List<string> result = new List<string>();
foreach (IEnumerable<string> chunk in chunks)
{
    result.Add(string.Join(":",chunk));                             
}

.......

static class LinqExtensions
{
    public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> list, int parts)
    {
        int i = 0;
        var splits = from item in list
                     group item by i++ % parts into part
                     select part.AsEnumerable();
        return splits;
    }
}

我清楚地了解你的目标吗?

[编辑] 在我看来,如果考虑性能,更好的方法是使用 String.Split 方法进行分块

于 2012-07-09T12:41:41.427 回答
0

您似乎想在“:”上拆分(您可以使用拆分方法)。然后你必须在拆分到每个已拆分的块后添加“:”。(然后,您可以在“,”上拆分所有已被“:”拆分的字符串。

于 2012-07-09T11:24:00.750 回答
0
int index = yourstring.IndexOf(":");

string[] whatever = string.Substring(0,index);

yourstring = yourstring.Substring(index); //make a new string without the part you just cut out.

这是一个通用视图示例,您需要做的就是建立一个迭代,该迭代将在遇到“:”字符时运行;干杯...

于 2012-07-09T11:26:45.543 回答