2017-09-27 12 views
1

ファイルストレージストリームが既に添付されているDataWriterがあります。どのように私は最初にメモリにデータを書きたいので、私はバイトのサイズを知ることができ、ライターにデータのサイズを格納することができます。MemoryStreamからDataWriterにディスクに書き込む方法

2つのメモリバッファを作成せずにどうすればいいですか?

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 
} 

私が分かるように、私は2つのバッファを使用しています.1つはメモリストリーム用、もう1つはibufferです。

ファイル格納ストリームが既に添付されているDataWriterに、メモリ内容を直接書き込む方法がわかりません。

+2

あなたはランダムアクセス(シーク可能)ストリーム、位置をマークしている場合は、0の長さを書き込み、ストリームに直接書き込むと、あなたはバイトだったどのように多くの知っていれば正しい値で長さを上書き書きました。注:私はUWPと 'DataWriter'について全く何も知っていません。これはあなたが一般的にそれをやっているところです。 –

+0

@ JeroenMostert DataWriterにはシークメソッドがありません。基本ストリームはランダムアクセスとシークをサポートします。データライターはそれを包み込んでいるので、基になるストリームに直接アクセスすることはできません。 DataWriterはシーケンシャルライターで、ストリームにデータを書き込むための使いやすいメソッドを提供します(BinaryWriterなど)。これは独自のバッファを持ち、バッファを基になるストリームにコミットすることもできないこともあるので、シークはサポートされていません。 –

答えて

0

重複したバッファ作成を防ぐために、私自身のバッファストリームを書き込む必要がありました。ストリームバッファは内部的にはリストのように機能しますが、リストが大きくなると利点があります。

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 
} 
関連する問題