看到很多人解析歌词文件时写了一大片的字符处理代码,而且看得不是很明白,所以自己研究了一下,
首先来了解下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; } |
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。