7

I want to read a locally stored file into a byte array. How do I do that? This is my try:

StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(filePath);
var file = await folder.GetFileAsync(filePath);
var buffer = await FileIO.ReadBufferAsync(file);
DataReader dataReader = Windows.Storage.Streams.DataReader.FromBuffer(buffer);
// doesn't work because ReadBytes wants a byte[] as parameter and also isn't asynchronous
byte[] result = dataReader.ReadBytes(buffer.Length);
testing
  • 19,681
  • 50
  • 236
  • 417
  • [This site](https://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh758325.aspx) mentions that I should use `DataReader`. It is not intended to have a difference. As result I want to have a `byte[]`. – testing Mar 18 '16 at 11:30
  • How do I convert the buffer to a byte[]? – testing Mar 18 '16 at 11:51
  • You're right, I got tripped up again. I find the new API sometimes confusing in its naming. – H H Mar 18 '16 at 11:57
  • @HenkHolterman: For converting from buffer to byte[] I found [this](https://social.msdn.microsoft.com/Forums/sqlserver/en-US/53c8401f-b70a-4c00-93a1-e66862a28035/uwp-replacement-for-systemiofilereadallbytes?forum=wpdevelop). Didn't try it out yet. – testing Mar 18 '16 at 12:34

3 Answers3

12

I think the other answers make things unnecessarily complicated. There is a convenient extension method IBuffer.ToArray() for this purpose.

Simply do this:

using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Storage;
...
IStorageFile file;
IBuffer buffer = await FileIO.ReadBufferAsync(file);
byte[] bytes = buffer.ToArray();
Daniel Rosenberg
  • 616
  • 5
  • 14
  • IBuffer buffer = FileIO.ReadBufferAsync(file); needs an await, and where's the ToArray() method? – Adrian K Apr 03 '17 at 07:45
  • 2
    Right you are - I have added the await. Regarding the ToArray() it's an extension method defined in System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeBufferExtensions, that's why I import that namespace in my example. – Daniel Rosenberg Apr 04 '17 at 11:13
9
        StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
        StorageFile sampleFile = await storageFolder.GetFileAsync(FILE_NAME);

        byte[] result;
        using (Stream stream = await sampleFile.OpenStreamForReadAsync())
        {
            using (var memoryStream = new MemoryStream())
            {

                stream.CopyTo(memoryStream);
                result = memoryStream.ToArray();
            }
        }
matihuf
  • 352
  • 1
  • 11
1

Three concepts come to my mind - using FileStream and modyfing your method little:

  • the first reads bytes via a provided buffer, though this method needs seekable stream:

    FileOpenPicker picker = new FileOpenPicker();
    picker.FileTypeFilter.Add(".txt");
    using (Stream fileStr = await (await picker.PickSingleFileAsync()).OpenStreamForReadAsync())
    {
        byte[] bytes = new byte[fileStr.Length];
        const int BUFFER_SIZE = 1024;
        byte[] buffer = new byte[BUFFER_SIZE];
        int position = 0;
        int bytesread = 0;
        while ((bytesread = await fileStr.ReadAsync(buffer, 0, BUFFER_SIZE)) > 0)
           for (int i = 0; i < bytesread; i++, position++)
               bytes[position] = buffer[i];
    }
    
  • the second method asynchronously copies filestream to memory then gets it as an array:

    using (MemoryStream memStream = new MemoryStream())
    using (Stream fileStr = await (await picker.PickSingleFileAsync()).OpenStreamForReadAsync())
    {
        await fileStr.CopyToAsync(memStream);
        byte[] bytes = memStream.ToArray();
    }
    
  • your method with little mdification - processing via memory stream:

    var buffer = await FileIO.ReadBufferAsync(file);
    using (MemoryStream mstream = new MemoryStream())
    {
         await buffer.AsStream().CopyToAsync(mstream);
         byte[] result = mstream.ToArray();
    }
    

Or maybe better you can avoid using byte[] and instead use IBuffer or MemoryStream.

Romasz
  • 29,662
  • 13
  • 79
  • 154
  • Hey @Romasz, what would drive you to use one of these approaches over the other? – Adrian K Apr 03 '17 at 07:49
  • @AdrianK In fact I would avoid using arrays and go for *Streams*. Choosing the method also depend on platform, predicted file size and its purpose. – Romasz Apr 03 '17 at 08:06