好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

C#解析Lrc歌词文件过程详解

看到很多人解析歌词文件时写了一大片的字符处理代码,而且看得不是很明白,所以自己研究了一下,
 首先来了解下lrc文件
 时间格式:
 1、标准格式: [分钟:秒.毫秒] 歌词
 注释: 括号、冒号、点号全都要求英文输入状态;
  2、其他格式①:[分钟:秒] 歌词;
 3、其他格式②:[分钟:秒:毫秒] 歌词,与标准格式相比,秒后边的点号被改成了冒号。

标准格式:
 其格式为"[标识名:值]"。大小写等价。以下是预定义的标签。
[ar:艺人名]
[ti:曲名]
[al:专辑名] 
[by:编者(指编辑lrc歌词的人)] 
[offset:时间补偿值] 其单位是毫秒,正值表示整体提前,负值相反。这是用于总体调整显示快慢的。
标准好啊,我就按照标准来做了 

 

?

public class lrc

{

  /// <summary>

  /// 歌曲

  /// </summary>

  public string title { get ; set ; }

  /// <summary>

  /// 艺术家

  /// </summary>

  public string artist { get ; set ; }

  /// <summary>

  /// 专辑

  /// </summary>

  public string album { get ; set ; }

  /// <summary>

  /// 歌词作者

  /// </summary>

  public string lrcby { get ; set ; }

  /// <summary>

  /// 偏移量

  /// </summary>

  public string offset { get ; set ; }

 

  /// <summary>

  /// 歌词

  /// </summary>

  public dictionary< double , string > lrcword = new dictionary< double , string >();

 

  /// <summary>

  /// 获得歌词信息

  /// </summary>

  /// <param name="lrcpath">歌词路径</param>

  /// <returns>返回歌词信息(lrc实例)</returns>

  public static lrc initlrc( string lrcpath)

  {

   lrc lrc = new lrc();

   using (filestream fs = new filestream(lrcpath, filemode.open, fileaccess.read, fileshare.read))

   {

    string line;

    using (streamreader sr = new streamreader(fs, encoding. default ))

    {

     while ((line = sr.readline()) != null )

     {

      if (line.startswith( "[ti:" ))

      {

       lrc.title = splitinfo(line);

      }

      else if (line.startswith( "[ar:" ))

      {

       lrc.artist = splitinfo(line);

      }

      else if (line.startswith( "[al:" ))

      {

       lrc.album = splitinfo(line);

      }

      else if (line.startswith( "[by:" ))

      {

       lrc.lrcby = splitinfo(line);

      }

      else if (line.startswith( "[offset:" ))

      {

       lrc.offset = splitinfo(line);

      }

      else

      {

       regex regex = new regex( @"\[([0-9.:]*)\]+(.*)" , regexoptions测试数据piled);

       matchcollection mc = regex.matches(line);

       double time = timespan.parse( "00:" + mc[0].groups[1].value).totalseconds;

       string word = mc[0].groups[2].value;

       lrc.lrcword.add(time, word);

      }

     }

    }

   }

   return lrc;

  }

 

  /// <summary>

  /// 处理信息(私有方法)

  /// </summary>

  /// <param name="line"></param>

  /// <returns>返回基础信息</returns>

  static string splitinfo( string line)

  {

   return line.substring(line.indexof( ":" ) + 1).trimend( ']' );

  }

}

一行代码:lrc lrc= lrc.initlrc("test.lrc"); 

我将分离好的歌词放入了dictionary<double, string>里,当然也可以直接用数组存,格式就要看实际的用途了,把这些都交给timespan来做吧。 
测试: 

很久以前有人提出了这个问题:一行歌词里面有多个时间会报错,这么久了也没见人把好的方案提供出来,今天我花了点时间,修改了下,下面是获取歌词方法 

 

?

/// <summary>

   /// 获得歌词信息

   /// </summary>

   /// <param name="lrcpath">歌词路径</param>

   /// <returns>返回歌词信息(lrc实例)</returns>

   public static lrc initlrc( string lrcpath)

   {

    lrc lrc = new lrc();

    dictionary< double , string > dicword = new dictionary< double , string >();

    using (filestream fs = new filestream(lrcpath, filemode.open, fileaccess.read, fileshare.read))

    {

     string line;

     using (streamreader sr = new streamreader(fs, encoding. default ))

     {

      while ((line = sr.readline()) != null )

      {

       if (line.startswith( "[ti:" ))

       {

        lrc.title = splitinfo(line);

       }

       else if (line.startswith( "[ar:" ))

       {

        lrc.artist = splitinfo(line);

       }

       else if (line.startswith( "[al:" ))

       {

        lrc.album = splitinfo(line);

       }

       else if (line.startswith( "[by:" ))

       {

        lrc.lrcby = splitinfo(line);

       }

       else if (line.startswith( "[offset:" ))

       {

        lrc.offset = splitinfo(line);

       }

       else

       {

        try

        {

         regex regexword = new regex( @".*\](.*)" );

         match mcw = regexword.match(line);

         string word = mcw.groups[1].value;

         regex regextime = new regex( @"\[([0-9.:]*)\]" , regexoptions测试数据piled);

         matchcollection mct = regextime.matches(line);

         foreach (match item in mct)

         {

          double time = timespan.parse( "00:" + item.groups[1].value).totalseconds;

          dicword.add(time, word);

         }

        }

        catch

        {

         continue ;

        }

       }

      }

     }

    }

    lrc.lrcword = dicword.orderby(t => t.key).todictionary(t => t.key, p => p.value);

    return lrc;

   }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

dy("nrwz");

查看更多关于C#解析Lrc歌词文件过程详解的详细内容...

  阅读:59次