2

TCPlistnerから次の形式の大きな文字列を受け入れました

"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:2/1/2012 、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 "

これは、コンマで区切られたフィールドであるレコードを含む:で区切られた文字列であることがわかります。

文字列を指定された数のチャンクに分割し、1つのチャンクに完全なレコード(「:」までの文字列)が含まれるように注意する最良の(最速の)方法を探しています

または他の言い方をすれば、で終わらないチャンクがあってはなりません:

たとえば、20MBの文字列からそれぞれ適切なレコードを持つ5MBの4つのチャンク(したがって、各チャンクのサイズは正確に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

OK、次の 2 つの手順をお勧めします。

  1. 文字列をチャンクに分割します (以下を参照)
  2. チャンクの完全性をチェックする

linq を使用して文字列をチャンクに分割します ( LINQ でコレクションを `n` 部分に分割しますか?から取得した 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

「:」で分割したいようです(Splitメソッドを使用できます)。次に、分割された各チャンクに分割した後、「:」を追加する必要があります。(その後、「:」で分割されたすべての文字列に対して「、」で分割できます。

于 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 に答える