2013-04-01 74 views
4

我在讀取Windows Phone SD卡上的文件時遇到問題。我使用ExternalStorageFile.OpenForReadAsync獲取有效的Stream對象。但是,雖然流CanSeek屬性爲true,但任何查找操作都將被忽略並且位置不會移動;Windows Phone 8 SD卡上的文件讀取問題

private async void ReadFileOnSDCard(ExternalStorageFile file) 
    { 
     Stream stream = await file.OpenForReadAsync(); 
      using (stream) 
      { 
       long curPos= stream.Seek(100, SeekOrigin.Begin); 
       long pos = stream.Position; 

//既CURPOS和POS爲0

+0

可能重複的MemoryStream和完整的原始流](http://stackoverflow.com/questions/20836625/composite-stream-wrapper-providing-partial-memorystream-and-full-original-stream) –

回答

0

我猜你正在閱讀與擴展,是reserved by Windows Phone文件。 不幸的是,你無法從Windows Phone上的SD卡上讀取它們。 如果您正在閱讀的文件屬於這些保留的擴展名,Windows Phone只是簡單地忽略它們。

假設您沒有閱讀那些保留的擴展名,您可以按照以下兩個步驟來解決您的問題。

1 /首先檢查,看看是否已經添加 <Capability Name="ID_CAP_REMOVABLE_STORAGE" />到您的WMAppManifest.xml

2 /註冊文件關聯的擴展,如果你沒有,例如.GPX

<FileTypeAssociation TaskID="_default" Name="GPX" NavUriFragment="fileToken=%s"> 
    <Logos> 
    <Logo Size="small" IsRelative="true">Assets/Route_Mapper_Logo33x33.png</Logo> 
    <Logo Size="medium" IsRelative="true">Assets/Route_Mapper_Logo69x69.png</Logo> 
    <Logo Size="large" IsRelative="true">Assets/Route_Mapper_Logo176x176.png</Logo> 
    </Logos> 
    <SupportedFileTypes> 
    <FileType ContentType="application/gpx">.gpx</FileType> 
    </SupportedFileTypes> 
</FileTypeAssociation> 
2

我在與同樣的問題鬥爭。 Seek確實在Microsoft.Phone.Storage.NativeFileStream中被破壞,這是SD卡上文件的流類型。最後,我看着與ILspy類,這是它:

public override long Seek(long offset, System.IO.SeekOrigin origin) 
{ 
    ... 
    uint num = (uint)((ulong)(offset & -4294967296L) >> 32); 
    uint num2 = (uint)(offset & (long)((ulong)-1)); 
    uint num3 = NativeFileStream.SetFilePointer(this.m_handle, num, ref num2, 
    ... 
} 

和功能SetFilePointer:http://msdn.microsoft.com/en-us/library/windows/desktop/aa365541%28v=vs.85%29.aspx

爲了找工作,偏移值應在長期的高32位。

+0

我想我自己也碰到了同樣的問題。那麼你只是用垃圾/ 0填充你的文件,所以你可以更深入地開始你的文件到文件?如果我的措辭有點粗糙,比我習慣的時候要低一級。 – Gavin

+0

我不知道是否有可能從Microsoft.Phone.Storage.NativeFileStream繼承並重寫Seek方法? – Gavin

+0

NativeFileStream的實例是您在SD卡上打開文件時得到的,因此覆蓋不是我認爲的解決方案。我有一個簡單的Stream包裝類,帶有overriden Seek,在調用基礎Stream的Seek方法之前,我將偏移值轉移到了更高的32位。 – Ales

0

如果文件很小,那麼您可以簡單地將該流複製到MemoryStream中。我測試了這一點,它的工作原理:

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

但是,如果文件過大,你會運行內存問題所以下面流包裝類可用於糾正微軟的bug(儘管在未來的版本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

的[複合流包裝提供部分