看到很多人解析歌词文件时写了一大片的字符处理代码,而且看得不是很明白,所以自己研究了一下,
首先来了解下lrc文件
时间格式:
1、标准格式: [分钟:秒.毫秒] 歌词
注释:括号、冒号、点号全都要求英文输入状态;
2、其他格式①:[分钟:秒] 歌词;
3、其他格式②:[分钟:秒:毫秒] 歌词,与标准格式相比,秒后边的点号被改成了冒号。
标准格式:
其格式为"[标识名:值]"。大小写等价。以下是预定义的标签。
[ar:艺人名]
[ti:曲名]
[al:专辑名]
[by:编者(指编辑lrc歌词的人)]
[offset:时间补偿值] 其单位是毫秒,正值表示整体提前,负值相反。这是用于总体调整显示快慢的。
标准好啊,我就按照标准来做了
?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
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.compiled);
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来做吧。
测试:


很久以前有人提出了这个问题:一行歌词里面有多个时间会报错,这么久了也没见人把好的方案提供出来,今天我花了点时间,修改了下,下面是获取歌词方法
?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
/// <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.compiled);
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;
}
|


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








发表评论
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。