簡體   English   中英

如何在WinRT中將數據從流保存到文件?

[英]How to save data from stream to file in WinRT?

我想有一個方法,將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);
                        }
                    }
                }
            }
        }

    }

問題是,當我嘗試在while周期(首次讀取)中讀取數據時,引發了異常(超出范圍)。 流應該有數據。 我不確定是否需要這么長時間的代碼,如果有人有更好的解決方案,那會很棒。 旁注:如果我嘗試await reader.LoadAsync(50)它將返回50。我不確定LoadAsync應該做什么。 也許我必須在讀取之前調用它以准備讀取的數據? 我將對此進行進一步調查。此外,Stream.CanRead返回true。

問題不在於我最初認為的轉換流。 只是缺少有關如何在WinRT中完成文件處理的知識(我認為Microsoft的文檔確實很糟糕)。

最后,在我的同事的幫助下,嘗試了幾種方法,最終得到以下結果:

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

我希望看到一些更簡單的實現,但這可行。 問題在於缺少LoadAsync (似乎必須調用它),並且在寫操作期間必須調用StoreAsync才能提交數據(刷新不足)。

希望對您有所幫助。

我建議不要使用這種代碼,而應利用Windows Runtime Interop擴展方法 這將產生更整潔,更易讀的代碼,例如:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM