none
win8 app中如何获通过uri获取非本地音乐文件的艺术家,唱片集等详细信息!通过httpclient无法seek文件流截取MP3信息!求高手指点。 RRS feed

  • 问题

  • 本人想通过HttpClient的方法得到网络音乐文件流,在从流中截取出包含了唱片信息的内容。但是到了seek的时候会提示不能seek,请高手指点下如何才能得到MP3文件的唱片,艺术家信息!

    下面是我写的代码


                    Uri uri = new Uri("http://10.0.0.11/data/UsbDisk1/Volume1/takemetoyourheart.mp3", UriKind.Absolute);
                    HttpClient httpclick = new HttpClient();
                    using (Stream responseStream = await response.Content.ReadAsStreamAsync())
                    {
                        responseStream.Seek(128, SeekOrigin.End);   //到达这里就提示错误了
                        const int iSeekPort = 128;
                        int iLenth = 0;
                        byte[] Info = new byte[iSeekPort];
                        iLenth = responseStream.Read(Info, 0, iSeekPort);

                        string strTiltle = UTF8Encoding.UTF8.GetString(Info, 0, 33);
                        string MusicAuthor = UTF8Encoding.UTF8.GetString(Info, 33, 30);  //艺术家
                        string MusicRador = UTF8Encoding.UTF8.GetString(Info, 63, 30);    //唱片集

                  }

    错误信息

    2013年10月15日 5:00

答案

  • Hi

    果然是我本地测试的歌不带有ID3的标签,我后来查看了下,并非是Begin,而是End,但是不是128,而是-128,我的代码如下:

    StorageFolder musicFolder = KnownFolders.MusicLibrary;
    StorageFile a = await musicFolder.GetFileAsync("takemetoyourheart.mp3");

    using (Stream responseStream = await a.OpenStreamForReadAsync()) { responseStream.Seek(-128, SeekOrigin.End); //到达这里就提示错误了 //SeekOrigin.End const int iSeekPort = 128; int iLenth = 0; byte[] Info = new byte[iSeekPort]; iLenth = responseStream.Read(Info, 0, iSeekPort); //strTitle应该是从3开始,0-3是“TAG” string strTiltle = UTF8Encoding.UTF8.GetString(Info, 0, 33); string MusicAuthor = UTF8Encoding.UTF8.GetString(Info, 33, 30); //艺术家 string MusicRador = UTF8Encoding.UTF8.GetString(Info, 63, 30); //唱片集 }

    远端问题我正在测试,稍后给你回复。


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.



    2013年10月18日 0:48
    版主
  • Hi

    关于远端问题,我的代码如下:

    HttpClient httpclick = new HttpClient();
    Uri uri = new Uri("你的地址", UriKind.Absolute);
    var httpResponse = await httpclick.GetAsync(uri);
    byte[] b = await httpResponse.Content.ReadAsByteArrayAsync();
    
    string strfrist2 = System.Text.UTF8Encoding.UTF8.GetString(b, b.Length - 128+3, 30);
    string MusicAuthor2 = System.Text.UTF8Encoding.UTF8.GetString(b, b.Length - 128+3 + 30,30); 
    string MusicRador2 = System.Text.UTF8Encoding.UTF8.GetString(b, b.Length - 128+3 + 30 + 30, 30);
    

    效果如下:

    我刚开始的思路也被带着拐弯了,一心想用StreamReader来实现,但实际上你的代码中有两个问题

    1,你并不知道文件的长度就通过 char[] myCharList = new char[1024 * 1024]; 来定义一个char的长度,会使代码很难找到对应的搜索点,尤其是我在测试你代码的时候,发现文件的后半截根本没有写入到myCharList中,这也就是为什么根本都不出ID3的原因。

    2,已经获取了byte就可以不再使用stream来读取,某种程度来说byte是更加底层的东西,所以直接从byte中读取即可。

    还有一个想附带说一个建议,你的MP3文件的大小为6M左右,我这里下载的话会非常慢,每次都是需要30秒左右的等待时间,你是否可以做一个类似于缓存的东西来确保用户体验。

    Best Regards

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.


    2013年10月18日 2:32
    版主

全部回复

  • Anyone can tell me How can i get the Mp3 ID3 in win8 app ?
    2013年10月15日 6:05
  • Hi Billy-NuoYan,

    一般来说通过HTTP方式获得的Stream是无法获取它的length(也有例外,有时候HTTP通过头文件就已经把长度发送给你,不过这种情况也有很大的误差率,所以一般默认为Stream无法获得准确的长度),这也就是为什么会在 SeekOrigin.End 的地方报错。

    解决的办法是使用StreamReader方式来实现。

    以上请参考。

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    2013年10月15日 7:40
    版主
  • 谢谢!Jamles!  按照你说的使用StreamReader方法,现在遇到另外一个问题就是,MP3 ID3在这里没的位置是在哪就不清楚了,使用Stream是分别在33开始,和63开始,现在用这个方法就不知道在哪个位置来得到艺术家和唱片集了。

    还请再帮忙看下。

    HttpClient httpclick = new HttpClient();
                    Uri uri = new Uri("http://10.0.0.11/data/UsbDisk1/Volume1/takemetoyourheart.mp3", UriKind.Absolute);
                    var httpResponse = await httpclick.GetAsync(uri);
                    byte[] b = await httpResponse.Content.ReadAsByteArrayAsync();
                    Stream tt = await httpclick.GetStreamAsync(uri);

      char[] myCharList = new char[1024 * 1024];
                   using (StreamReader sread = new StreamReader(tt))
                   {
                       sread.Read(myCharList, 0, myCharList.Length);
                       byte[]  bpara = System.Text.UTF8Encoding.UTF8.GetBytes(myCharList);
                       string strfrist2 = System.Text.UTF8Encoding.UTF8.GetString(bpara, 0, bpara.Length);
                       string MusicAuthor2 = System.Text.UTF8Encoding.UTF8.GetString(bpara, 33, 30);   //艺术家     这个好像不是33位开始-用StreamReader 方法现在开始位置应该设置为多少呢?
                       string MusicRador2 = System.Text.UTF8Encoding.UTF8.GetString(bpara, 63, 30);    //唱片集       好像不是在63位开始
                   }

    2013年10月15日 10:35
  • Hi Billy-NuoYan,

    我没有测你的代码,不过我大概看了下,你第一段中使用responseStream.Seek(128, SeekOrigin.End); 有一个128位的偏移量,之后才有33和63的获取,我猜想是否因为第二段代码中你并没有设置偏移量导致数据错误?

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    2013年10月16日 0:48
    版主
  • 使用了StreamReader 后该在哪个地方进行seek,设置偏移量呢?Stream 又没有,StreamReader 也没有seek,StreamReader.basestream 后又回到原来的stream 又是同样不能seek。
    2013年10月16日 1:11
  • Hi Billy-NuoYan,

    我的意思是按你原来的用法是用128位开始偏移,33是基于128而言的位置,那是否可以尝试修改StreamReader.Read()的参数方式来获取艺术家信息? sread.Read(myCharList, 128, myCharList.Length); 这样的话你的myCharList是从128位开始的。

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    2013年10月17日 0:54
    版主
  • 谢谢jamles!我试过sread.Read(myCharList, 128, myCharList.Length); 和sread.Read(myCharList, myCharList.Length - 128, 128); 这样处理的结果也是还不正确!不知道怎么弄了!
    2013年10月17日 1:18
  • 好的,下午我来研究下,然后再给你答复 :P

    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    2013年10月17日 1:20
    版主
  • 非常感谢Jamles!

    2013年10月17日 1:32
  • Hi Billy-NuoYan,

    我测试的时候遇到几个问题,帮忙确认下吧。

    第一个问题,如果使用第一段代码获取一个本地音乐文件的属性是否能成功?我试了下貌似不行(或许是我测试的mp3没有ID3的Tag,如果是这样的话能发给我一个有ID3 Tag的音乐文件么?),得出的结果都是"\0"之类的符号,但是如果我把代码改成下面的,也就是Seek的位置从Begin开始,似乎就可以看到你所需要的东西包含在内。

     responseStream.Seek(128, SeekOrigin.Begin);   

    所以我不清楚是否你本身的定位就错了?如果我通过await file.Properties.GetMusicPropertiesAsync();倒是可以准确的获得Title,艺术家和唱片集的信息。

    同时你的第二段代码是基于第一段代码改写而来,所以很有可能第二段代码的处理思路跟第一段代码一样,导致获取的值也有偏差。我之后又搜索到一个帖子: http://social.msdn.microsoft.com/Forums/en-US/9a66f067-7220-40aa-9c9a-fdb98ddcd464/streamreader-problem?forum=Vsexpressvb 貌似有提到编码的问题,我再看看是否还有其他东西可以帮到你

    Best Regards,

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.


    2013年10月17日 7:44
    版主
  • Hi!Jamles   对于你提到用第一段代码获取一个本地音乐文件的属性,我没有成功,不知道是我写的有问题还是怎么样,也是提示stream不能seek,我是先通过storagefile通过本地音乐文件地址获取到文件,再通过file.open得到流,在进行seek的,但也是不能seek。我是这样写的:StorageFile file = await StorageFile.GetFileFromPathAsync("C:\\Users\\HCQ\\Music\\takemetoyourheart.mp3");
                IRandomAccessStream randstream = await file.OpenAsync(FileAccessMode.Read);
                Stream stream = randstream as Stream;
                stream.Seek(128, SeekOrigin.Begin);    //这里一样提示不能Seek

    你说你改成responseStream.Seek(128, SeekOrigin.Begin);   就可以了,前面一些代码是怎么样的?能贴下我学习下嘛 

    我本地文件正是使用你说的await file.Properties.GetMusicPropertiesAsync这种方式得到相应信息的。

    我上传了一首有相应唱片信息,艺术家信息的歌曲到skydrive,你可以下来测试下。https://skydrive.live.com/redir?resid=56C8C9A332A136A7!109&authkey=!AIofyhHfTRO0Ugs

    现在就卡在这个远端的问题上,还的麻烦你多帮帮忙!

    2013年10月17日 10:52
  • Hi

    果然是我本地测试的歌不带有ID3的标签,我后来查看了下,并非是Begin,而是End,但是不是128,而是-128,我的代码如下:

    StorageFolder musicFolder = KnownFolders.MusicLibrary;
    StorageFile a = await musicFolder.GetFileAsync("takemetoyourheart.mp3");

    using (Stream responseStream = await a.OpenStreamForReadAsync()) { responseStream.Seek(-128, SeekOrigin.End); //到达这里就提示错误了 //SeekOrigin.End const int iSeekPort = 128; int iLenth = 0; byte[] Info = new byte[iSeekPort]; iLenth = responseStream.Read(Info, 0, iSeekPort); //strTitle应该是从3开始,0-3是“TAG” string strTiltle = UTF8Encoding.UTF8.GetString(Info, 0, 33); string MusicAuthor = UTF8Encoding.UTF8.GetString(Info, 33, 30); //艺术家 string MusicRador = UTF8Encoding.UTF8.GetString(Info, 63, 30); //唱片集 }

    远端问题我正在测试,稍后给你回复。


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.



    2013年10月18日 0:48
    版主
  • Hi

    关于远端问题,我的代码如下:

    HttpClient httpclick = new HttpClient();
    Uri uri = new Uri("你的地址", UriKind.Absolute);
    var httpResponse = await httpclick.GetAsync(uri);
    byte[] b = await httpResponse.Content.ReadAsByteArrayAsync();
    
    string strfrist2 = System.Text.UTF8Encoding.UTF8.GetString(b, b.Length - 128+3, 30);
    string MusicAuthor2 = System.Text.UTF8Encoding.UTF8.GetString(b, b.Length - 128+3 + 30,30); 
    string MusicRador2 = System.Text.UTF8Encoding.UTF8.GetString(b, b.Length - 128+3 + 30 + 30, 30);
    

    效果如下:

    我刚开始的思路也被带着拐弯了,一心想用StreamReader来实现,但实际上你的代码中有两个问题

    1,你并不知道文件的长度就通过 char[] myCharList = new char[1024 * 1024]; 来定义一个char的长度,会使代码很难找到对应的搜索点,尤其是我在测试你代码的时候,发现文件的后半截根本没有写入到myCharList中,这也就是为什么根本都不出ID3的原因。

    2,已经获取了byte就可以不再使用stream来读取,某种程度来说byte是更加底层的东西,所以直接从byte中读取即可。

    还有一个想附带说一个建议,你的MP3文件的大小为6M左右,我这里下载的话会非常慢,每次都是需要30秒左右的等待时间,你是否可以做一个类似于缓存的东西来确保用户体验。

    Best Regards

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.


    2013年10月18日 2:32
    版主
  • 谢谢Jamles! 学习了!
    2013年10月18日 4:06
  • 谢谢Jamles! 学习了!

    wjm

    2013年10月18日 10:12