2014-10-09 147 views
0

我想有一個方法,它將一個System.IO.Stream作爲輸入並使用它將數據寫入文件。到目前爲止,我有以下幾點:如何將數據從流保存到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); 
         } 
        } 
       } 
      } 
     } 

    } 

問題是,當我嘗試讀while循環(先讀)數據的異常(超出範圍)被拋出。流應該有數據。我不確定是否這麼長的代碼是壞的,如果有人有更好的解決方案,它會很好。 附註: 如果我嘗試await reader.LoadAsync(50)它返回50.我不確定LoadAsync應該做什麼。也許我必須在閱讀之前調用它以準備讀取數據?我將進一步調查... 此外,Stream.CanRead返回true。

回答

1

問題不在於轉換流,正如我原先的想法。這只是缺乏知識如何在WinRT中完成文件的工作(我認爲微軟的文檔非常糟糕)。

與我collegue與嘗試多種方式的幫助下結束,並與下面的結束:

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以提交數據(刷新不足)。

我希望這可以幫助別人。

0

我會建議不要那種代碼,而應該利用Windows Runtime Interop extension methods。這將產生更整潔和更可讀的代碼,例如:

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); 
    } 
} 
相關問題