2016-09-18 152 views
1

我正在使用Mp3流光。要從url流式傳輸mp3文件,我想使用臨時文件。但試圖讀取和寫入相同的文件爲File.ReadAllBytes拋出IOException,因爲該文件正在使用中。我怎樣才能解決這個問題?如何使用臨時文件流式傳輸mp3文件?

long pos = 0; 
string path = pathtothetempfile; 
MemoryStream ms = new MemoryStream(); 
FileStream fs = new FileStream(path, FileMode.Create, 
           FileAccess.ReadWrite, FileShare.ReadWrite); 

do 
{ 
    bytesRead = responseStream.Read(buffer, 0, buffer.Length); 

    fs.Write(buffer, 0, bytesRead); 
    fs.Flush(); 

    byte[] tempBuffer = File.ReadAllBytes(path); 

    pos = ms.Position; 
    ms = new MemoryStream(tempBuffer); 
    ms.Position = pos; 

    frame = Mp3Frame.LoadFromStream(ms); 

    //....codes.... 
} 
while(bytesRead > 0) 
+0

使用資源管理器來測試在打開文件時是否可以訪問文件:嘗試將文件複製到某處。如果失敗,打開該文件的程序將不允許共享訪問,並且在程序中無法執行任何操作來打開它。 – Robert

回答

0

我已經找到了一個答案,我自己通過搜索這麼多。這個答案包含NAudio來控制Mp3,並且通過部分讀取流來實現RAM友好。我將其分享給有同樣問題的其他人。

WaveOut waveOut; 
    AcmMp3FrameDecompressor decompressor; 
    BufferedWaveProvider provider; 
    bool firstPlay = true; 

    public void Play() 
    { 
     Task.Run(() => 
     { 

      #region WebRequest creator 
      HttpWebResponse response = null; 
      if (avgbytes < 0) 
      { 
       HttpWebRequest req = WebRequest.Create(url) as HttpWebRequest; 
       req.AllowAutoRedirect = true; 
       req.UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0"; 
       response = req.GetResponse() as HttpWebResponse; 
       contentLength = response.ContentLength; 
      } 
      else 
       response = Helper.CreateAudioWebRequest(url, currentTime, avgbytes) 
           .GetResponse() as HttpWebResponse; 

      Stream responseStream = response.GetResponseStream(); 
      #endregion 

      #region Local Variables 
      byte[] buffer = new byte[17 * 1024]; 
      byte[] bigBuffer = new byte[response.ContentLength]; 
      int bytesRead = 0; 
      long pos = 0; 
      long postotal = 0; 
      string path = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".mp3"; 
      #endregion 

      Mp3Frame frame; 
      FileStream fs = new FileStream(path, 
       FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite); 
      do 
      { 
       bytesRead = responseStream.Read(buffer, 0, buffer.Length); 
       fs.Write(buffer, 0, bytesRead); 
       fs.Flush(); 
       using (MemoryStream ms = new MemoryStream(ReadPartial(fs, postotal, 1024 * 10))) 
       { 
        ms.Position = 0; 
        frame = Mp3Frame.LoadFromStream(ms); 
        if (frame == null) 
        { 
         continue; 
        } 
        pos = ms.Position; 
        postotal += pos; 
       } 


       #region First Play 
       if (firstPlay) 
       { 
        avgbytes = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, 
       frame.FrameLength, frame.BitRate).AverageBytesPerSecond; 
        duration = (int)(response.ContentLength * 1d/avgbytes); 
        firstPlay = false; 
       } 
       #endregion 

       #region Decompress Frame 
       if (decompressor == null) 
       { 
        decompressor = CreateFrameDecompressor(frame) as AcmMp3FrameDecompressor; 
        provider = new BufferedWaveProvider(decompressor.OutputFormat); 
        provider.BufferDuration = TimeSpan.FromSeconds(20); 
       } 
       int decompressed = decompressor.DecompressFrame(frame, buffer, 0); 
       #endregion 

       #region BufferedWaveProvider Area 
       if (IsBufferNearlyFull(provider)) 
       { 
        Thread.Sleep(500); 
       } 
       provider.AddSamples(buffer, 0, decompressed); 
       #endregion 


       if (provider.BufferedDuration.TotalSeconds >= 2 && waveOut == null) 
       { 
        waveOut = new WaveOut(); 
        waveOut.Init(provider); 
        waveOut.Play(); 
       } 
      } 
      while (postotal != contentLength || bytesRead > 0 || waveOut==null || 
         (waveOut != null && waveOut.PlaybackState == PlaybackState.Playing)); 

     }); 
    } 

    public static byte[] ReadStreamPartially(System.IO.Stream stream, long offset, long count) 
    { 
     long originalPosition = 0; 

     if (stream.CanSeek) 
     { 
      originalPosition = stream.Position; 
      stream.Position = offset; 
     } 

     try 
     { 
      byte[] readBuffer = new byte[4096]; 
      byte[] total = new byte[count]; 
      int totalBytesRead = 0; 
      int byteRead; 

      while ((byteRead = stream.ReadByte()) != -1) 
      { 
       Buffer.SetByte(total, totalBytesRead, (byte)byteRead); 
       totalBytesRead++; 
       if (totalBytesRead == count) 
       { 
        stream.Position = originalPosition; 
        break; 
       } 
      } 
      if (totalBytesRead < count) 
      { 
       byte[] temp = new byte[totalBytesRead]; 
       Buffer.BlockCopy(total, 0, temp, 0, totalBytesRead); 
       stream.Position = originalPosition; 
       return temp; 
      } 
      return total; 
     } 
     finally 
     { 
      if (stream.CanSeek) 
      { 
       stream.Position = originalPosition; 
      } 
     } 
    } 

    private bool IsBufferNearlyFull(BufferedWaveProvider bufferedWaveProvider) 
    { 
     return bufferedWaveProvider != null && 
       bufferedWaveProvider.BufferLength - bufferedWaveProvider.BufferedBytes 
       < bufferedWaveProvider.WaveFormat.AverageBytesPerSecond/4; 
    } 
    private static IMp3FrameDecompressor CreateFrameDecompressor(Mp3Frame frame) 
    { 
     WaveFormat waveFormat = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, 
      frame.FrameLength, frame.BitRate); 
     return new AcmMp3FrameDecompressor(waveFormat); 
    }