【问题标题】:Not able to copy a stream to a file无法将流复制到文件
【发布时间】:2012-12-28 16:34:31
【问题描述】:

我必须从 SpeechSynthesizer 生成的流中创建一个音频文件。

这是我正在使用的代码

var stream = await _SpeechSynth.GetSpeakStreamAsync(text, this.Language);
            var reader = new Windows.Storage.Streams.DataReader(stream.GetInputStreamAt(0));
            await reader.LoadAsync((uint)stream.Size);

            byte[] bytes = new byte[stream.Size];
            reader.ReadBytes(bytes);

             var audioFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync(_AgendaAudioFilename, CreationCollisionOption.ReplaceExisting);

             using (var outputStream = await audioFile.OpenAsync(FileAccessMode.ReadWrite))
             {

                 Stream os = outputStream.GetOutputStreamAt(0).AsStreamForWrite();
                 await os.WriteAsync(bytes, 0, bytes.Length);
             }

我发现问题在于“os.WriteAsync”没有被等待。当我在该行放置断点并等待几秒钟时,文件正在正确创建。 await 关键字不应该等到所有字节都复制到流中再转到下一行吗?

我不介意是否有人可以建议将 InMemoryRandomAccessStream 复制到文件的更好方法?

编辑:

Mahantesh 的回答很有魅力。非常感谢。但我面临一个新问题。

创建文件后,我试图再次打开它以播放它,但出现此错误。

“访问被拒绝。(来自 HRESULT 的异常:0x80070005 (E_ACCESSDENIED))”

这是我的代码。

if (!cacheHit)
        {
            var stream = await _SpeechSynth.GetSpeakStreamAsync(text, this.Language);

            //write the stream to disk (seems to be buggy when attempting to playback from the result of the speech synth request)
            var audioFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync(_AgendaAudioFilename, CreationCollisionOption.ReplaceExisting);

             outputStream = await audioFile.OpenAsync(FileAccessMode.ReadWrite);

             await RandomAccessStream.CopyAsync(stream, outputStream);                 

        }

        //read agenda from disk and play back the audio
        var agendaStorageFile = await ApplicationData.Current.TemporaryFolder.GetFileAsync(_AgendaAudioFilename);
        var agendaStreamFromDisk = await agendaStorageFile.OpenAsync(FileAccessMode.Read);            

        _MediaPlayer.Url = text;
        _MediaPlayer.SetBytestream(agendaStreamFromDisk);
        _MediaPlayer.Play();    

我在这一行得到错误:

var agendaStreamFromDisk = await agendaStorageFile.OpenAsync(FileAccessMode.Read);

知道可能出了什么问题吗?

【问题讨论】:

    标签: c# file-io windows-8 microsoft-metro windows-runtime


    【解决方案1】:

    我觉得你可以试试

    await RandomAccessStream.CopyAsync(inMemoryStream, outputStream);
    

    新问题的解决方案:

    if (!cacheHit)
        {
            var stream = await _SpeechSynth.GetSpeakStreamAsync(text, this.Language);
    
            //write the stream to disk (seems to be buggy when attempting to playback from the result of the speech synth request)
            var audioFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync(_AgendaAudioFilename, CreationCollisionOption.ReplaceExisting);
    
             using(outputStream = await audioFile.OpenAsync(FileAccessMode.ReadWrite)){
             await RandomAccessStream.CopyAsync(stream, outputStream);}
    
        }
    
        //read agenda from disk and play back the audio
        var agendaStorageFile = await ApplicationData.Current.TemporaryFolder.GetFileAsync(_AgendaAudioFilename);
       using (var agendaStreamFromDisk = await agendaStorageFile.OpenAsync(FileAccessMode.Read)){
    
        _MediaPlayer.Url = text;
        _MediaPlayer.SetBytestream(agendaStreamFromDisk);
        _MediaPlayer.Play();  }
    

    【讨论】:

    • 非常感谢您的回答。但是当我试图打开文件时,我面临着一个新问题。我已经编辑了这个问题,你能告诉我哪里可能出错了吗?
    • 下次打开前需要关闭输出流(outputStream .Close)或尝试“使用”块
    【解决方案2】:

    当您使用 await 关键字等待时,最好使用同步版本的方法,例如

    using (var outputStream = audioFile.Open(FileAccessMode.ReadWrite))
    {
        Stream os = outputStream.GetOutputStreamAt(0).AsStreamForWrite();
        os.Write(bytes, 0, bytes.Length);
    }
    

    【讨论】:

    • 即使这样也行不通.....不知道!但是,当我在 os.Write 之后放置一个断点并在下一行等待几秒钟时,输出流会得到一些大小。真的很奇怪。知道会发生什么吗?
    猜你喜欢
    • 1970-01-01
    • 2020-04-01
    • 2017-09-06
    • 1970-01-01
    • 1970-01-01
    • 2021-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多