3

バイト ストリームをサイズが大きくなるチャンクに分割しようとしています。

ソース ストリームに不明なバイト数が含まれており、読み取りにコストがかかります。列挙子の出力は、8KB から 1MB まで増加するサイズのバイト配列である必要があります。

これは、ストリーム全体を読み取って配列に格納し、関連する部分を取り出すだけで、非常に簡単に実行できます。ただし、ストリームは非常に大きい場合があるため、一度に読み取ることはできません。また、パフォーマンスは主な関心事ではありませんが、システムの負荷を非常に低く保つことが重要です。

これを実装しているときに、コードを短く維持しやすくするのは比較的難しいことに気付きました。留意すべきストリーム関連の問題もいくつかあります (たとえば、Stream.Read は成功してもバッファーがいっぱいにならない場合があります)。

私のケースに役立つ既存のクラスは見つかりませんでしたし、ネット上でそれに近いものを見つけることもできませんでした。そのようなクラスをどのように実装しますか?

4

2 に答える 2

4
public IEnumerable<BufferWrapper> getBytes(Stream stream)
{
    List<int> bufferSizes = new List<int>() { 8192, 65536, 220160, 1048576 };
    int count = 0;
    int bufferSizePostion = 0;
    byte[] buffer = new byte[bufferSizes[0]];
    bool done = false;
    while (!done)
    {
        BufferWrapper nextResult = new BufferWrapper();
        nextResult.bytesRead = stream.Read(buffer, 0, buffer.Length);
        nextResult.buffer = buffer;
        done = nextResult.bytesRead == 0;
        if (!done)
        {
            yield return nextResult;
            count++;
            if (count > 10 && bufferSizePostion < bufferSizes.Count)
            {
                count = 0;
                bufferSizePostion++;
                buffer = new byte[bufferSizes[bufferSizePostion]];
            }
        }
    }
}

public class BufferWrapper
{
    public byte[] buffer { get; set; }
    public int bytesRead { get; set; }
}

明らかに、バッファ サイズをいつ上げるかのロジックと、そのサイズを選択する方法は変更できます。

これは最も効率的な方法ではないため、送信される最後のバッファーを処理するより良い方法を誰かがおそらく見つけることもできます。

于 2012-02-06T16:00:09.050 に答える
2

参考までに、私が現在使用している実装は、@Servy の回答に従ってすでに改善されています

private const int InitialBlockSize = 8 * 1024;
private const int MaximumBlockSize = 1024 * 1024;

private Stream _Stream;
private int _Size = InitialBlockSize;

public byte[] Current
{
    get;
    private set;
}

public bool MoveNext ()
{
    if (_Size < 0) {
        return false;
    }

    var buf = new byte[_Size];
    int count = 0;

    while (count < _Size) {
        int read = _Stream.Read (buf, count, _Size - count);

        if (read == 0) {
            break;
        }

        count += read;
    }

    if (count == _Size) {
        Current = buf;
        if (_Size <= MaximumBlockSize / 2) {
            _Size *= 2;
        }
    }
    else {
        Current = new byte[count];
        Array.Copy (buf, Current, count);
        _Size = -1;
    }

    return true;
}
于 2012-02-06T16:29:59.540 に答える