Загрузить файл с SD-карты

Я интегрировал в свой проект программу чтения (this)EPUB Reader. Он работает нормально. & Я хочу загрузить файл с SDCard вместо изолированного хранилища устройства

Чтобы открыть файл из изолированного хранилища, у нас есть IsolatedStorageFileStream вот так

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

ePubView.Source = isfs;

Для файла на SD-карте я пробовал так

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;
 }

Здесь я получаю исключение System.IO.EndOfStreamException

введите здесь описание изображения

Если хотите, попробуйте.. Вот пример моего проекта ссылка

Вопрос: как передать свой файл в качестве источника элементу управления epubView

Это правильный путь, пожалуйста, дайте предложение по этому поводу.. Спасибо


person Kumar    schedule 28.01.2014    source источник
comment
Так это работает? У вас есть какие-то особые проблемы?   -  person richzilla    schedule 28.01.2014
comment
Выглядит нормально. Не забудьте добавить FileTypeAssociation в свой манифест.   -  person Romasz    schedule 28.01.2014
comment
Я добавил FileTypeAssociation в манифест и почти забыл упомянуть об исключении. Я отредактировал вопрос   -  person Kumar    schedule 28.01.2014
comment
Я добавил пример проекта здесь [sdrv.ms/1b0pXWv]   -  person Kumar    schedule 28.01.2014


Ответы (2)


Хотя я не пробовал ваш подход, и я не могу точно сказать, где ошибка (может быть, файл с SD читается асинхронно и, таким образом, вы получаете EndOfStream, и, пожалуйста, имейте в виду, что, как сказано на сайте EPUB Reader - он находится под тяжелым развитие). Проверьте, сможете ли вы после копирования файла в ISolatedStorage использовать его.
Я бы попробовал в этом случае сначала скопировать с SD в поток памяти следующим образом:

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;
} 

И 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;
}

Может быть, это поможет.

person Romasz    schedule 28.01.2014
comment
@Romsaz Работает впервые. После этого не работает.. дает нулевое значение. Вот ссылка из MSDN. [social.msdn.microsoft.com/Forums/wpapps/en-US/ ] Спасибо, что дали мне надежду начать.. - person Kumar; 30.01.2014
comment
@kumar мой код был написан без проверки - я рад, что он сработал. Где взять ноль? И что вы имеете в виду, говоря, что дальше не работает - когда? - person Romasz; 30.01.2014

Ошибка с потоком, возвращаемым из ExternalStorageFile. Есть два варианта как обойти...

Если файл небольшой, вы можете просто скопировать поток в MemoryStream:

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

Однако, если файл слишком велик, вы столкнетесь с проблемами памяти, поэтому для исправления ошибки Microsoft можно использовать следующий класс оболочки потока (хотя в будущих версиях Windows Phone вам нужно будет отключить это исправление, как только ошибка будет устранена). фиксированный):

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);
        }
    }
}

Здесь доступен код для добавления в ваш проект: https://github.com/gavinharriss/ExternalStorageFileWrapper-wp8< /а>

Пример использования:

ExternalStorageFile file = await device.GetFileAsync(filename); // device is an instance of ExternalStorageDevice
Stream streamOriginal = await file.OpenForReadAsync();
ExternalStorageFileWrapper streamToUse = new ExternalStorageFileWrapper(streamOriginal);
person Gavin    schedule 25.02.2014
comment
Извините за очень поздний ответ. & Да, для некоторых файлов мой проект не работает. Я добавил ваш проект в свое решение и действительно не понял, как использовать ваш код в ExternalStorageFileWrapper class. Не могли бы вы подсказать, что делать после получения файлового потока. ExternalStorageFileWrapper EFW = new ExternalStorageFileWrapper(s); - person Kumar; 05.03.2014
comment
Пример кода внизу github.com/gavinharriss/ExternalStorageFileWrapper-wp8 — делает это помочь тебе? ExternalStorageFileWrapper реализует интерфейс Stream, поэтому его можно использовать вместо исходного потока. - person Gavin; 05.03.2014
comment
Да .. Я использовал этот код, кажется, проблема с моим кодом после получения файла с SD-карты. не проблема с вашим ExternalStorageFileWrapper. Позвольте мне проверить еще несколько возможностей. Я сообщу о статусе результата здесь. Спасибо - person Kumar; 06.03.2014