Stream 读取Windows Phone 8 SD卡上的文件时出现问题
我无法读取Windows Phone SD卡上的文件。我使用ExternalStorageFile.OpenForReadAsync获取有效的流对象。但是,尽管stream CanSeek属性为true,但忽略任何查找操作,并且不移动位置Stream 读取Windows Phone 8 SD卡上的文件时出现问题,stream,windows-phone-8,sd-card,seek,Stream,Windows Phone 8,Sd Card,Seek,我无法读取Windows Phone SD卡上的文件。我使用ExternalStorageFile.OpenForReadAsync获取有效的流对象。但是,尽管stream CanSeek属性为true,但忽略任何查找操作,并且不移动位置 private async void ReadFileOnSDCard(ExternalStorageFile file) { Stream stream = await file.OpenForReadAsync();
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的文件。 不幸的是,您无法从Windows Phone上的SD卡读取它们。 如果您正在读取的文件属于这些保留扩展名,Windows Phone只需忽略它们即可 假设您没有阅读这些保留的扩展,您可以按照以下两个步骤来解决问题 1/首先检查是否已添加
到您的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>
资源/路线\u映射器\u Logo33x33.png
资源/路线\u映射器\u Logo69x69.png
资源/路线\u映射器\u Logo176x176.png
.gpx
我也在为同样的问题而斗争。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:
要使寻道工作,偏移量值应该在长的32位以上。如果文件很小,则可以简单地将流复制到MemoryStream。我已经对此进行了测试,并且效果良好:
Stream s = await file.OpenForReadAsync();
MemoryStream ms = new MemoryStream();
s.CopyTo(ms);
但是,如果文件太大,您将遇到内存问题,因此可以使用以下流包装器类来纠正Microsoft的错误(尽管在Windows Phone的未来版本中,一旦错误得到修复,您需要禁用此修复):
使用系统;
使用System.IO;
命名空间WindowsPhoneBugFix
{
///
///流包装器,用于绕过ExternalStorageFile.OpenForReadAsync()返回的流的错误流读取
///
公共密封类ExternalStorageFileWrapper:流
{
私有流_Stream;//底层流
公共ExternalStorageFileWrapper(流)
{
if(流==null)
抛出新的ArgumentNullException(“流”);
_溪流=溪流;
}
//此处描述的解决方法-http://stackoverflow.com/a/21538189/250254
公共覆盖长寻道(长偏移,参见原始坐标系)
{
ulong uoffset=(ulong)偏移量;
ulong fix=((uoffset&0xffffffffffl)>32);
返回_stream.Seek((长)固定,原点);
}
公共覆盖布尔可读取
{
获取{return\u stream.CanRead;}
}
公共覆盖布尔搜索
{
获取{return\u stream.CanSeek;}
}
公共覆盖布尔可写
{
获取{return\u stream.CanWrite;}
}
公共覆盖无效刷新()
{
_stream.Flush();
}
公共覆盖长长度
{
获取{return\u stream.Length;}
}
公众优先多头仓位
{
得到
{
返回流位置;
}
设置
{
_流。位置=值;
}
}
公共重写整型读取(字节[]缓冲区、整型偏移量、整型计数)
{
返回_stream.Read(缓冲区、偏移量、计数);
}
公共覆盖无效设置长度(长值)
{
_stream.SetLength(值);
}
公共重写无效写入(字节[]缓冲区、整数偏移量、整数计数)
{
_写入(缓冲区、偏移量、计数);
}
}
}
此处有代码可用于访问您的项目:
我想我自己也遇到了同样的问题。那么,您是否只是简单地用垃圾/0填充文件,以便可以在文件的更深处开始偏移量?比我习惯的级别低一点,所以如果我的措辞有点粗糙,我很抱歉。我想知道是否可以从Microsoft.Phone.Storage.NativeFileStream继承并覆盖Seek方法?NativeFileStream的实例是在SD卡上打开文件时得到的,所以我认为覆盖不是一个解决方案。我有一个简单的带有重写Seek的流包装器类,在调用底层流的Seek方法之前,我只需将传递的偏移量值移到更高的32位,这对我来说也是有效的。我的答案贴在下面。但为了方便起见,这里有一个指向代码的链接-可能是
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);
}
}
}