【问题标题】:How to write from MemoryStream into DataWriter into disk如何从 MemoryStream 写入 DataWriter 到磁盘
【发布时间】:2017-09-27 09:30:49
【问题描述】:

我的 DataWriter 已经附加了文件存储流。在特定情况下,我想先将数据写入内存,以便知道字节的大小,然后将大小与数据一起存储在写入器中。

如何在不创建两个内存缓冲区的情况下做到这一点?

DataWriter writer; // writer is parameter passed from somewhere else.

using (var inMemory = new InMemoryRandomAccessStream())
{
    // fill inMemory with data.

    // ***Here*** How can I avoid this?
    var buffer = new byte[checked((int)inMemory.Position)].AsBuffer();

    inMemory.Seek(0);
    await inMemory.ReadAsync(buffer, buffer.Length, InputStreamOptions.ReadAhead);

    writer.WriteUInt32(buffer.Length); // write size
    writer.WriteBuffer(buffer); // write data
}

如您所见,我使用了两个缓冲区,一个用于内存流,另一个用于 ibuffer。

我不知道如何将 inMemory 的内容直接写入已经附加了文件存储流的 DataWriter 中。

【问题讨论】:

  • 如果你有一个随机访问(可搜索的)流,标记位置,写入长度为 0,将字节直接写入流,然后在知道有多少后用正确的值覆盖长度字节被写入。注意:我对 UWP 和 DataWriter 一无所知,这就是你一般的做法。
  • @JeroenMostert DataWriter 没有 seek 方法。底层流支持随机访问和查找。但是数据写入器是围绕它的包装器,所以我无法直接访问底层流。 DataWriter 是顺序写入器,它提供了易于使用的方法将数据写入流,(如 BinaryWriter)。它有自己的缓冲区,可能会也可能不会将缓冲区提交到底层流中,所以我想这就是不支持搜索的原因。

标签: c# uwp datawriter


【解决方案1】:

我必须编写自己的缓冲区流,以防止创建重复的缓冲区。虽然流缓冲区在内部像列表一样工作,但当列表变大时它有好处。

internal sealed class BufferStream : IDisposable
{
    private byte[] _array = Array.Empty<byte>();
    private int _index = -1;
    private const int MaxArrayLength = 0X7FEFFFFF;

    public int Capacity => _array.Length;
    public int Length => _index + 1;

    public void WriteIntoDataWriterStreamAsync(IDataWriter writer)
    {
        // AsBuffer wont cause copy, its just wrapper around array.
        if(_index >= 0) writer.WriteBuffer(_array.AsBuffer(0, _index)); 
    }

    public void WriteBuffer(IBuffer buffer)
    {
        EnsureSize(checked((int) buffer.Length));

        for (uint i = 0; i < buffer.Length; i++)
        {
            _array[++_index] = buffer.GetByte(i);
        }
    }

    public void Flush()
    {
        Array.Clear(_array, 0, _index);
        _index = -1;
    }

    // list like resizing.
    private void EnsureSize(int additionSize)
    {
        var min = additionSize + _index;
        if (_array.Length <= min)
        {
            var newsize = (int) Math.Min((uint) _array.Length * 2, MaxArrayLength);
            if (newsize <= min) newsize = min + 1;
            Array.Resize(ref _array, newsize);
        }
    }

    public void Dispose()
    {
        _array = null;
    }
}

那么我可以轻松做到这一点。

using (var buffer = new BufferStream())
{
    // fill buffer

    writer.WriteInt32(buffer.Length); // write size
    buffer.WriteIntoDataWriterStream(writer); // write data
}

【讨论】:

    猜你喜欢
    • 2023-03-29
    • 2018-07-31
    • 2013-08-10
    • 2014-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-07
    相关资源
    最近更新 更多