title: How to read byte data from a StorageFile in cppwinrt?
body: <p>A 2012 answer at StackOverflow (“How do I read a binary file in a Windows Store app”) suggests this method of reading byte data from a StorageFile in a Windows Store app:</p>
  
  
  
  <pre class="lang-cpp prettyprint-override"><code>IBuffer buffer = await FileIO.ReadBufferAsync(theStorageFile);
  byte[] bytes = buffer.ToArray();
  </code></pre>
  
  <p>That looks simple enough. As I am working in cppwinrt I have translated that to the following, within the same IAsyncAction that produced a vector of StorageFiles. First I obtain a StorageFile from the VectorView using theFilesVector.GetAt(index);</p>
  
  <p>//Then this line compiles without error:</p>
  
  <pre class="lang-cpp prettyprint-override"><code>IBuffer buffer = co_await FileIO::ReadBufferAsync(theStorageFile);
  </code></pre>
  
  <p>//But I can’t find a way to make the buffer call work.</p>
  
  <pre class="lang-cpp prettyprint-override"><code>byte[] bytes = buffer.ToArray();
  </code></pre>
  
  <p>“byte[]” can’t work, to begin with, so I change that to byte*, but then
  the error is “class ‘winrt::Windows::Storage::Streams::IBuffer’ has no member ‘ToArray’”</p>
  
  <p>And indeed Intellisense lists no such member for IBuffer. Yet IBuffer was specified as the return type for ReadBufferAsync. It appears the above sample code cannot function as it stands.</p>
  
  <p>In the documentation for FileIO I find it recommended to use DataReader to read from the buffer, which in cppwinrt should look like </p>
  
  <pre class="lang-cpp prettyprint-override"><code>DataReader dataReader = DataReader::FromBuffer(buffer);
  </code></pre>
  
  <p>That compiles. It should then be possible to read bytes with the following DataReader method, which is fortunately supplied in the UWP docs in cppwinrt form:</p>
  
  <pre class="lang-cpp prettyprint-override"><code>void ReadBytes(Byte[] value) const;
  </code></pre>
  
  <p>However, that does not compile because the type Byte is not recognized in cppwinrt. If I create a byte array instead:</p>
  
  <pre class="lang-cpp prettyprint-override"><code>byte* fileBytes = new byte(buffer.Length());
  </code></pre>
  
  <p>that is not accepted. The error is </p>
  
  <pre class="lang-cpp prettyprint-override"><code>‘No suitable constructor exists to convert from “byte*” to “winrt::arrayView::&lt;uint8_t&gt;”’ 
  </code></pre>
  
  <p>uint8_t is of course a byte, so let’s try</p>
  
  <pre class="lang-cpp prettyprint-override"><code>uint8_t fileBytes = new uint8_t(buffer.Length());
  </code></pre>
  
  <p>That is wrong - clearly we really need to create a winrt::array_view. Yet a 2015 Reddit post says that array_view “died” and I’m not sure how to declare one, or if it will help. That original one-line method for reading bytes from a buffer is looking so beautiful in retrospect. This is a long post, but can anyone suggest the best current method for simply reading raw bytes from a StorageFile reference in cppwinrt? It would be so fine if there were simply GetFileBytes() and GetFileBytesAsync() methods on StorageFile.</p>
  
  <p>---Update: here's a step forward. I found a comment from Kenny Kerr last year explaining that array_view should not be declared directly, but that std::vector or std::array can be used instead. And that is accepted as an argument for the ReadBytes method of DataReader:</p>
  
  <pre class="lang-cpp prettyprint-override"><code>std::vector&lt;unsigned char&gt;fileBytes;
  dataReader.ReadBytes(fileBytes);
  </code></pre>
  
  <p>Only trouble now is that the std::vector is receiving no bytes, even though the size of the referenced file is correctly returned in buffer.Length() as 167,513 bytes. That seems to suggest the buffer is good, so I'm not sure why the ReadBytes method applied to that buffer would produce no data.</p>
  
  <p>Update #2:  Kenny suggests reserving space in the vector, which is something I had tried, this way:</p>
  
  <pre class="lang-cpp prettyprint-override"><code>m_file_bytes.reserve(buffer.Length());
  </code></pre>
  
  <p>But it didn't make a difference. Here is a sample of the code as it now stands, using DataReader.</p>
  
  <pre class="lang-cpp prettyprint-override"><code>buffer = co_await FileIO::ReadBufferAsync(nextFile);
  dataReader = DataReader::FromBuffer(buffer);
  //The following line may be needed, but crashes
  //co_await dataReader.LoadAsync(buffer.Length());
  if (buffer.Length())
  {
  m_file_bytes.reserve(buffer.Length());
  dataReader.ReadBytes(m_file_bytes);
  }
  The crash, btw, is 
  
  throw hresult_error(result, hresult_error::from_abi);
  </code></pre>
  
  <p>Is it confirmed, then, that the original 2012 solution quoted above cannot work in today's world? But of course there must be some way to read bytes from a file, so I'm just missing something that may be obvious to another.</p>
  
  <p>Final (I think) update: Kenny's suggestion that the vector needs a size has hit the mark. If the vector is first prepared with m_file_bytes.assign(buffer.Length(),0) then it does get filled with file data. Now my only worry is that I don't really understand the way IAsyncAction is working and maybe could have trouble looping this asynchronously, but we'll see.</p>