0

I integrated (this)EPUB Reader reader to my project. It is working fine. & I want to load the file from SDCard instead of Isolated storage of device

To open file from Isolated storage we have IsolatedStorageFileStream like this

IsolatedStorageFileStream isfs;
using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
{
    try
    {
        isfs = isf.OpenFile([Path to file], FileMode.Open);
    }
    catch
    {
        return;
    }
}

ePubView.Source = isfs;

For file in SDcard I tried like this

ExternalStorageDevice sdCard = (await ExternalStorage.GetExternalStorageDevicesAsync()).FirstOrDefault();

// If the SD card is present, get the route from the SD card.
if (sdCard != null)
{
    ExternalStorageFile file = await sdCard.GetFileAsync(_sdFilePath);
    // _sdFilePath is string that having file path of file in SDCard

    // Create a stream for the route.
    Stream file = await file.OpenForReadAsync();

    // Read the route data.
    ePubView.Source = file;
 }

Here I am getting exception System.IO.EndOfStreamException

enter image description here

If You want try.. Here is my project sample link

Question : How can I give my file as source to epubView control

Is this is proper way, please give a suggestion regarding this.. Thanks

Kumar
  • 864
  • 1
  • 22
  • 46

2 Answers2

0

Although I've not tried your approach, and I cannot say exactly where is an error (maybe file from SD is read async and thus you get EndOfStream, and please keep in mind that as it is said at EPUB Reader Site - it's under heavy developement). Check if after copying the file to ISolatedStorage, you will be able to use it.
I would try in this case first copying from SD to Memory stream like this:

ExternalStorageDevice sdCard = (await ExternalStorage.GetExternalStorageDevicesAsync()).FirstOrDefault();

if (sdCard != null)
{
   MemoryStream newStream = new MemoryStream();
   using (ExternalStorageFile file = await sdCard.GetFileAsync(_sdFilePath))
    using (Stream SDfile = await file.OpenForReadAsync())
      newStream = await ReadToMemory(SDfile);

   ePubView.Source = newStream;
} 

And ReadToMemory:

private async Task<MemoryStream> ReadToMemory(Stream streamToRead)
{
   MemoryStream targetStream = new MemoryStream();

   const int BUFFER_SIZE = 1024;
   byte[] buf = new byte[BUFFER_SIZE];
   int bytesread = 0;
   while ((bytesread = await streamToRead.ReadAsync(buf, 0, BUFFER_SIZE)) > 0)
   {
       targetStream.Write(buf, 0, bytesread);
   }
   return targetStream;
}

Maybe it will help.

Romasz
  • 29,662
  • 13
  • 79
  • 154
  • @Romsaz It is working for first time. After onwards not working.. giving null value. Here is the link from MSDN. [http://social.msdn.microsoft.com/Forums/wpapps/en-US/851d2c46-67c4-4930-a037-25e2462ba80a/load-file-from-sdcard-in-epubreader?forum=wpdevelop#3438b1f3-4cd9-41af-8fe2-b737bc1b98a9 ] Thanks for giving me hope to start.. – Kumar Jan 30 '14 at 13:01
  • @kumar my code was written without checking it - I'm glad that it worked. Where do you get null? And what do you mean by onwards not working - when? – Romasz Jan 30 '14 at 14:11
0

There's a bug with the stream returned from ExternalStorageFile. There's two options to get around it...

If the file is small then you can simply copy the stream to a MemoryStream:

Stream s = await file.OpenForReadAsync();
MemoryStream ms = new MemoryStream();
s.CopyTo(ms);

However, if the file is too large you'll run in to memory issues so the following stream wrapper class can be used to correct Microsoft's bug (though in future versions of Windows Phone you'll need to disable this fix once the bug has been fixed):

using System;
using System.IO;

namespace WindowsPhoneBugFix
{
    /// <summary>
    /// Stream wrapper to circumnavigate buggy Stream reading of stream returned by ExternalStorageFile.OpenForReadAsync()
    /// </summary>
    public sealed class ExternalStorageFileWrapper : Stream
    {
        private Stream _stream; // Underlying stream

        public ExternalStorageFileWrapper(Stream stream)
        {
            if (stream == null)
                throw new ArgumentNullException("stream");

            _stream = stream;
        }

        // Workaround described here - http://stackoverflow.com/a/21538189/250254
        public override long Seek(long offset, SeekOrigin origin)
        {
            ulong uoffset = (ulong)offset;
            ulong fix = ((uoffset & 0xffffffffL) << 32) | ((uoffset & 0xffffffff00000000L) >> 32);
            return _stream.Seek((long)fix, origin);
        }

        public override bool CanRead
        {
            get { return _stream.CanRead; }
        }

        public override bool CanSeek
        {
            get { return _stream.CanSeek; }
        }

        public override bool CanWrite
        {
            get { return _stream.CanWrite; }
        }

        public override void Flush()
        {
            _stream.Flush();
        }

        public override long Length
        {
            get { return _stream.Length; }
        }

        public override long Position
        {
            get
            {
                return _stream.Position;
            }
            set
            {
                _stream.Position = value;
            }
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            return _stream.Read(buffer, offset, count);
        }

        public override void SetLength(long value)
        {
            _stream.SetLength(value);
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            _stream.Write(buffer, offset, count);
        }
    }
}

Code is available here to drop in to your project: https://github.com/gavinharriss/ExternalStorageFileWrapper-wp8

Example of use:

ExternalStorageFile file = await device.GetFileAsync(filename); // device is an instance of ExternalStorageDevice
Stream streamOriginal = await file.OpenForReadAsync();
ExternalStorageFileWrapper streamToUse = new ExternalStorageFileWrapper(streamOriginal);
Gavin
  • 5,629
  • 7
  • 44
  • 86
  • Sorry for very late reply. & Yes, for some files my project not working. I added your project to my solution & really I didn't understand that how to use your code in `ExternalStorageFileWrapper class`. Can you please suggest what to do after getting file stream. `ExternalStorageFileWrapper EFW = new ExternalStorageFileWrapper(s);` – Kumar Mar 05 '14 at 07:25
  • There's a code example at the bottom of https://github.com/gavinharriss/ExternalStorageFileWrapper-wp8 - does that help you? ExternalStorageFileWrapper implements the Stream interface so can be used in place of the original stream. – Gavin Mar 05 '14 at 09:48
  • Ya.. I used that Code, Seems problem with my code after getting file from SDcard. not the issue with your `ExternalStorageFileWrapper`. Let me check with some more possibilities. I will inform the status of result here. Thanks – Kumar Mar 06 '14 at 13:03