| 前段时间,在局域网里面做一个小网站,其中有板块是涉及音乐的在线播放。考虑到以后维护的方便,决定把mp3文件都按专辑分不同的目录存放。然后使用一个程序监控存放mp3的目录,把每个mp3文件的信息都存入数据库中,用过ASP.NET页面将mp3文件的信息呈现给用户。其中使用.NET来读取mp3 文件的信息虽然不难,但也需要不少技巧,故将该过程整理与大家分享。
首先我们来看看mp3歌曲的信息所存放的位置。Mp3文件包含一个叫做ID3的标签。其实有两个标签,一个叫做ID3v1,另外一个叫做ID3v2。为了讲述的简单起见,我们这里只介绍ID3v1。
ID3V1结构比较简单,存放在MP3文件的末尾,大家可以用16进制的编辑器(例如:UltraEdit)打开一个MP3文件,注意其末尾的128个字节,数据结构定义如下:
名称 位置 长度 内容
Header 1-3 3 标签头
Title 4-33 30 标题
Artist 34-63 30 艺术家
Album 64-93 30 专辑
Year 94-97 4 出品年代
Comment 98-127 30 备注
Cenre 128 1 类型
注意:上述的标签头必须是”TAG”, 否则表示没有标签
ID3v1的各项信息是按顺序依次存放的,每项信息之后并没有任何的结束标志,如果某项信息长度小于标准长度,使用”\0”来补充。另外Genre是个例外,它用一个字节表示歌曲流派,其对应表如下(由于该内容太多,只列出前50项):
0="Blues"
1="ClassicRock"
2="Country"
3="Dance"
4="Disco"
5="Funk"
6="Grunge"
7="Hip-Hop"
8="Jazz"
9="Metal"
10="NewAge"
11="Oldies"
12="Other"
13="Pop"
14="R&B"
15="Rap"
16="Reggae"
17="Rock"
18="Techno"
19="Industrial"
20="Alternative"
21="Ska"
22="DeathMetal"
23="Pranks"
24="Soundtrack"
25="Euro-Techno"
26="Ambient"
27="Trip-Hop"
28="Vocal"
29="Jazz+Funk"
30="Fusion"
31="Trance"
32="Classical"
33="Instrumental"
34="Acid"
35="House"
36="Game"
37="SoundClip"
38="Gospel"
39="Noise"
40="AlternRock"
41="Bass"
42="Soul"
43="Punk"
44="Space"
45="Meditative"
46="InstrumentalPop"
47="InstrumentalRock"
48="Ethnic"
49="Gothic"
50="Darkwave"
知道了MP3歌曲信息存放的结构之后,我们就可以写出对应的代码。
首先定一个MP3Info类:
1 Public Class Mp3Info 2 3 4 5 Private Const TAGLEN As Integer = 128 6 7 8 9 Private _MP3Tag As String = String.Empty 10 11 Private _Artist As String = String.Empty 12 13 Private _Title As String = String.Empty 14 15 Private _Album As String = String.Empty 16 17 Private _Comment As String = String.Empty 18 19 Private _Year As String = String.Empty 20 21 Private _Genre As String = String.Empty 22 23 Private _GenreID As Byte 24 25 26 27 Private Genres() As String = {"Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", _ 28 29 "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B", "Rap", "Reggae", "Rock", _ 30 31 "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", _ 32 33 "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental", "Acid", _ 34 35 "House", "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass", "Soul", "Punk", "Space", _ 36 37 "Meditative", "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", "Techno-Industrial", _ 38 39 "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta", "Top 40", _ 40 41 "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret", "New Wave", "Psychedelic", "Rave", _ 42 43 "Showtunes", "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", _ 44 45 "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk", "Swing", "Bebob", "Latin", "Revival", _ 46 47 "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", _ 48 49 "Slow Rock", "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson", "Opera", _ 50 51 "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", _ 52 53 "Tango", "Samba", "Folklore"} 54 55 56 57 Public Property MP3Tag() As String 58 59 Get 60 61 Return _MP3Tag 62 63 End Get 64 65 Set(ByVal value As String) 66 67 _MP3Tag = value.Trim 68 69 End Set 70 71 End Property 72 73 74 75 Public Property Title() As String 76 77 Get 78 79 Return _Title 80 81 End Get 82 83 Set(ByVal value As String) 84 85 _Title = value.Trim 86 87 End Set 88 89 End Property 90 91 92 93 Public Property Artist() As String 94 95 Get 96 97 Return _Artist 98 99 End Get 100 101 Set(ByVal value As String) 102 103 _Artist = value.Trim 104 105 End Set 106 107 End Property 108 109 110 111 Public Property Album() As String 112 113 Get 114 115 Return _Album 116 117 End Get 118 119 Set(ByVal value As String) 120 121 _Album = value.Trim 122 123 End Set 124 125 End Property 126 127 128 129 Public Property Comment() As String 130 131 Get 132 133 Return _Comment 134 135 End Get 136 137 Set(ByVal value As String) 138 139 _Comment = value.Trim 140 141 End Set 142 143 End Property 144 145 146 147 Public Property Genre() As String 148 149 Get 150 151 Return _Genre 152 153 End Get 154 155 Set(ByVal value As String) 156 157 _Genre = value.Trim 158 159 End Set 160 161 End Property 162 163 164 165 Public Property GenreID() As Byte 166 167 Get 168 169 Return _GenreID 170 171 End Get 172 173 Set(ByVal value As Byte) 174 175 _GenreID = value 176 177 End Set 178 179 End Property 180 181 182 183 Public Property Year() As String 184 185 Get 186 187 Return _Year 188 189 End Get 190 191 Set(ByVal value As String) 192 193 _Year = value.Trim 194 195 End Set 196 197 End Property 198 199 End Class 200 201 202 203 上面的类只包含了mp3歌曲信息对应的数据结构,我们还要为它添加具体读取mp3文件信息的过程: 204 205 206 207 Public Function GetMp3FileInfo(ByVal fname As String) As Boolean 208 209 210 211 'Open the filestream 212 213 Dim msfile As FileStream 214 215 Try 216 217 msfile = New FileStream(fname, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) 218 219 If Not (msfile.CanRead) Then 220 221 Throw New IO.IOException("无法读取文件:" + fname) 222 223 End If 224 225 Catch Ex As Exception 226 227 Throw New IO.IOException("读取文件发生错误!" + Ex.Message) 228 229 End Try 230 231 232 233 Dim ID3(TAGLEN - 1) As Byte 234 235 Dim BinReader As BinaryReader 236 237 Dim StrInfo As String 238 239 240 241 '使用BinaryReader来读取信息 242 243 BinReader = New BinaryReader(msfile) 244 245 246 247 msfile.Position = 0 248 249 msfile.Seek(-TAGLEN, SeekOrigin.End) 250 251 252 253 StrInfo = CBytesToString(BinReader.ReadBytes(3)) 254 255 256 257 '判断标签头是否为 TAG 258 259 If StrInfo.ToUpper = "TAG" Then 260 261 262 263 '读取标题信息 264 265 StrInfo = CBytesToString(BinReader.ReadBytes(30)).Replace(Chr(0), "") 266 267 _Title = StrInfo 268 269 270 271 '读取艺术家信息 272 273 StrInfo = CBytesToString(BinReader.ReadBytes(30)).Replace(Chr(0), "") 274 275 _Artist = StrInfo 276 277 278 279 '读取专辑信息 280 281 StrInfo = CBytesToString(BinReader.ReadBytes(30)).Replace(Chr(0), "") 282 283 _Album = StrInfo 284 285 286 287 '读取出版年度信息 288 289 StrInfo = CBytesToString(BinReader.ReadBytes(4)).Replace(Chr(0), "") 290 291 _Year = StrInfo 292 293 294 295 '读取备注信息 296 297 StrInfo = CBytesToString(BinReader.ReadBytes(30)).Replace(Chr(0), "") 298 299 _Comment = StrInfo 300 301 302 303 '读取歌曲流派信息 304 305 _GenreID = BinReader.ReadByte 306 307 308 309 End If 310 311 312 313 BinReader.Close() 314 315 msfile.Close() 316 317 318 319 End Function 320 321 322 323 '用于转换编码, 防止出现中文乱码 324 325 Private Function CBytesToString(ByVal Bytes() As Byte) As String 326 327 '注意这里 需要对编码进行处理, 防止出现乱码 328 329 Dim GbCode As Encoding = Encoding.GetEncoding("gb2312") 330 331 If Bytes.Length > 0 Then 332 333 Return GbCode.GetString(Bytes) 334 335 Else 336 337 Return String.Empty 338 339 End If 340 341 End Function
我们可以用一个简单的Console程序来说明,如何使用Mp3Info类。使用Visual Studio 2005 Express,创建一个Console程序:
1 Module Module1 2 3 4 5 Sub 6 7 8 9 Dim Mp3 As New Mp3Info("D:\Music\Top 40 Singles\39 Embrace - Natures Law.mp3") 10 11 12 13 Console.WriteLine("Title : " + Mp3.Title) 14 15 Console.WriteLine("Artist: " + Mp3.Artist) 16 17 Console.WriteLine("Album : " + Mp3.Album) 18 19 Console.Read() 20 21 End Sub 22 23 24 End Module
运行该程序后输出为:
Title : Nature's Law
Artist: Embrace
Album : DHZ.INC
Genre : Blues
本文只针对mp3的ID3v1进行了讨论,而实际上很多mp3不仅仅包含ID3v1的信息,还包含ID3v2的信息。
但ID3v2要比ID3v1复杂,对于ID3v2的处理,要等下次有空的时候再写了。
|