C# 如何在WinRT中将数据从流保存到文件?

C# 如何在WinRT中将数据从流保存到文件?,c#,stream,windows-runtime,windows-8.1,winrt-async,C#,Stream,Windows Runtime,Windows 8.1,Winrt Async,我希望有一个方法,它将System.IO.Stream作为输入,并使用它将数据从中写入文件。到目前为止,我有以下几点: public async Task SaveStreamToFileX(Stream stream, string filePath, IProgress<long> progress) { var folder = await StorageFolder.GetFolderFromPathAsync(Path.GetDirecto

我希望有一个方法,它将System.IO.Stream作为输入,并使用它将数据从中写入文件。到目前为止,我有以下几点:

    public async Task SaveStreamToFileX(Stream stream, string filePath, IProgress<long> progress)
    {

        var folder = await StorageFolder.GetFolderFromPathAsync(Path.GetDirectoryName(filePath));

        var fileName = Path.GetFileName(filePath);
        StorageFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists);

        var istream = stream.AsInputStream();

        var canRead = stream.CanRead; //this returns true

        using (var reader = new DataReader(istream))
        {
            using (IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.ReadWrite))
            {
                using (IOutputStream outputStream = fileStream.GetOutputStreamAt(0))
                {
                    using (DataWriter writer = new DataWriter(outputStream))
                    {
                        IBuffer buffer;
                        long readBytes = 0;
                        const int bufferSize = 8192;
                        while ((buffer = reader.ReadBuffer(bufferSize)).Length > 0) //exception System.Exception with message: Out of range ...
                        {
                            writer.WriteBuffer(buffer);
                            readBytes += bufferSize;
                            progress.Report(readBytes);
                        }
                    }
                }
            }
        }

    }
    public async Task SaveStreamToFile(Stream stream, string filePath, IProgress<long> progress )
    {
        var folder = await StorageFolder.GetFolderFromPathAsync(Path.GetDirectoryName(filePath));

        var fileName = Path.GetFileName(filePath);
        StorageFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists);

        var istream = stream.AsInputStream();

        using (var reader = new DataReader(istream))
        {
            using (IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.ReadWrite))
            {
                using (IOutputStream outputStream = fileStream.GetOutputStreamAt(0))
                {
                    using (DataWriter writer = new DataWriter(outputStream))
                    {
                        long writtenBytes = 0;
                        const int bufferSize = 8192;

                        uint loadedBytes = 0;
                        while ((loadedBytes = (await reader.LoadAsync(bufferSize))) > 0) //!!!
                        {
                            IBuffer buffer = reader.ReadBuffer(loadedBytes);
                            writer.WriteBuffer(buffer);
                            uint tmpWritten = await writer.StoreAsync(); //!!!
                            writtenBytes += tmpWritten;
                            progress.Report(writtenBytes);
                        }
                    }
                }
            }
        }
    }    
public异步任务SaveStreamToFileX(流、字符串文件路径、IProgress进程)
{
var folder=wait-StorageFolder.GetFolderFromPathAsync(Path.GetDirectoryName(filePath));
var fileName=Path.GetFileName(filePath);
StorageFile file=wait folder.CreateFileAsync(文件名,CreationCollisionOption.OpenIfExists);
var istream=stream.AsInputStream();
var canRead=stream.canRead;//返回true
使用(变量读取器=新数据读取器(istream))
{
使用(irandomaccesstream fileStream=await file.OpenAsync(FileAccessMode.ReadWrite))
{
使用(IOutputStream outputStream=fileStream.getoutputstreeamat(0))
{
使用(DataWriter writer=newdatawriter(outputStream))
{
伊布弗缓冲液;
long readBytes=0;
const int bufferSize=8192;
while((buffer=reader.ReadBuffer(bufferSize)).Length>0)//异常系统。异常消息:超出范围。。。
{
writer.WriteBuffer(缓冲区);
readBytes+=缓冲区大小;
进度报告(readBytes);
}
}
}
}
}
}
问题是,当我尝试在while循环(首次读取)中读取数据时,会引发异常(超出范围)。流应该有数据。我不确定是否需要这么长的代码,如果有人有更好的解决方案,那就太好了。 旁注: 如果我尝试
等待reader.LoadAsync(50)
它将返回50。我不确定LoadAsync应该做什么。也许我必须在读取之前调用它来为读取准备数据?我会进一步调查这件事。。。
此外,Stream.CanRead返回true

问题不在于我最初认为的转换流。只是缺少在WinRT中如何处理文件的知识(我认为微软的文档真的很糟糕)

最后,在我的同事的帮助下,我尝试了几种方法,并得出以下结论:

    public async Task SaveStreamToFileX(Stream stream, string filePath, IProgress<long> progress)
    {

        var folder = await StorageFolder.GetFolderFromPathAsync(Path.GetDirectoryName(filePath));

        var fileName = Path.GetFileName(filePath);
        StorageFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists);

        var istream = stream.AsInputStream();

        var canRead = stream.CanRead; //this returns true

        using (var reader = new DataReader(istream))
        {
            using (IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.ReadWrite))
            {
                using (IOutputStream outputStream = fileStream.GetOutputStreamAt(0))
                {
                    using (DataWriter writer = new DataWriter(outputStream))
                    {
                        IBuffer buffer;
                        long readBytes = 0;
                        const int bufferSize = 8192;
                        while ((buffer = reader.ReadBuffer(bufferSize)).Length > 0) //exception System.Exception with message: Out of range ...
                        {
                            writer.WriteBuffer(buffer);
                            readBytes += bufferSize;
                            progress.Report(readBytes);
                        }
                    }
                }
            }
        }

    }
    public async Task SaveStreamToFile(Stream stream, string filePath, IProgress<long> progress )
    {
        var folder = await StorageFolder.GetFolderFromPathAsync(Path.GetDirectoryName(filePath));

        var fileName = Path.GetFileName(filePath);
        StorageFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists);

        var istream = stream.AsInputStream();

        using (var reader = new DataReader(istream))
        {
            using (IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.ReadWrite))
            {
                using (IOutputStream outputStream = fileStream.GetOutputStreamAt(0))
                {
                    using (DataWriter writer = new DataWriter(outputStream))
                    {
                        long writtenBytes = 0;
                        const int bufferSize = 8192;

                        uint loadedBytes = 0;
                        while ((loadedBytes = (await reader.LoadAsync(bufferSize))) > 0) //!!!
                        {
                            IBuffer buffer = reader.ReadBuffer(loadedBytes);
                            writer.WriteBuffer(buffer);
                            uint tmpWritten = await writer.StoreAsync(); //!!!
                            writtenBytes += tmpWritten;
                            progress.Report(writtenBytes);
                        }
                    }
                }
            }
        }
    }    
public异步任务SaveStreamToFile(流、字符串文件路径、IProgress进程)
{
var folder=wait-StorageFolder.GetFolderFromPathAsync(Path.GetDirectoryName(filePath));
var fileName=Path.GetFileName(filePath);
StorageFile file=wait folder.CreateFileAsync(文件名,CreationCollisionOption.OpenIfExists);
var istream=stream.AsInputStream();
使用(变量读取器=新数据读取器(istream))
{
使用(irandomaccesstream fileStream=await file.OpenAsync(FileAccessMode.ReadWrite))
{
使用(IOutputStream outputStream=fileStream.getoutputstreeamat(0))
{
使用(DataWriter writer=newdatawriter(outputStream))
{
long writenbytes=0;
const int bufferSize=8192;
uint loadedBytes=0;
而((loadedBytes=(wait reader.LoadAsync(bufferSize)))>0)/!!!
{
IBuffer buffer=reader.ReadBuffer(loadedBytes);
writer.WriteBuffer(缓冲区);
uint tmpwrited=wait writer.StoreAsync();/!!!
writenbytes+=tmpwrited;
进度报告(writenbytes);
}
}
}
}
}
}    
我希望看到一些更简单的实现,但这是可行的。问题是缺少
LoadAsync
(这似乎是调用的必要条件),在写入操作期间,必须调用
StoreAsync
,才能提交数据(刷新不够)


我希望这对某些人有所帮助。

我建议不要使用这种代码,而是利用它。这将产生更整洁、可读性更强的代码,例如:

private async Task CopyToTempFile(Stream stream, string temporaryFileName) {

    var file = await ApplicationData.Current.TemporaryFolder.CreateFileAsync(temporaryFileName, CreationCollisionOption.ReplaceExisting);

    using (var outputstream = await file.OpenStreamForWriteAsync()) {
        await stream.CopyToAsync(outputstream);
    }
}