從MP3中提取歌曲信息(C#)
2024-07-21 02:18:24
供稿:網友
從mp3中提取歌曲信息
一首mp3歌曲除了音樂信息外,還包含了如歌名、演唱者等信息,當我們用winamp軟件聽音樂時,播放清單就自動將這些信息讀出來。大部分人都喜歡從網上下載音樂,但下載下來的mp3文件名都是文件上傳系統自動取名的,和歌曲本身根本不相符,所以,給用戶帶來了很大的麻煩。但是,懶人有懶人的做法,我們何不自己寫一個程序,將歌曲信息自動讀出來并為mp3文件自動更名呢?
下面我就以c#為工具,把開發過程寫出來。
一首mp3的額外信息存放在文件的最后面,共占128個字節,其中包括以下的內容(我們定義一個結構說明):
public struct mp3info
{
public string identify;//tag,三個字節
public string title;//歌曲名,30個字節
public string artist;//歌手名,30個字節
public string album;//所屬唱片,30個字節
public string year;//年,4個字符
public string comment;//注釋,28個字節
public char reserved1;//保留位,一個字節
public char reserved2;//保留位,一個字節
public char reserved3;//保留位,一個字節
}
所以,我們只要把mp3文件的最后128個字節分段讀出來并保存到該結構里就可以了。函數定義如下:
/// <summary>
/// 獲取mp3文件最后128個字節
/// </summary>
/// <param name="filename">文件名</param>
/// <returns>返回字節數組</returns>
private byte[] getlast128(string filename)
{
filestream fs = new filestream(filename,filemode.open,fileaccess.read);
stream stream = fs;
stream.seek(-128,seekorigin.end);
const int seekpos = 128;
int rl = 0;
byte[] info = new byte[seekpos];
rl = stream.read(info,0,seekpos);
fs.close();
stream.close();
return info;
}
再對上面返回的字節數組分段取出,并保存到mp3info結構中返回。
/// <summary>
/// 獲取mp3歌曲的相關信息
/// </summary>
/// <param name = "info">從mp3文件中截取的二進制信息</param>
/// <returns>返回一個mp3info結構</returns>
private mp3info getmp3info(byte[] info)
{
mp3info mp3info = new mp3info();
string str = null;
int i;
int position = 0;//循環的起始值
int currentindex = 0;//info的當前索引值
//獲取tag標識
for(i = currentindex;i<currentindex+3;i++)
{
str = str+(char)info[i];
position++;
}
currentindex = position;
mp3info.identify = str;
//獲取歌名
str = null;
byte[] byttitle = new byte[30];//將歌名部分讀到一個單獨的數組中
int j = 0;
for(i = currentindex;i<currentindex+30;i++)
{
byttitle[j] = info[i];
position++;
j++;
}
currentindex = position;
mp3info.title = this.bytetostring(byttitle);
//獲取歌手名
str = null;
j = 0;
byte[] bytartist = new byte[30];//將歌手名部分讀到一個單獨的數組中
for(i = currentindex;i<currentindex+30;i++)
{
bytartist[j] = info[i];
position++;
j++;
}
currentindex = position;
mp3info.artist = this.bytetostring(bytartist);
//獲取唱片名
str = null;
j = 0;
byte[] bytalbum = new byte[30];//將唱片名部分讀到一個單獨的數組中
for(i = currentindex;i<currentindex+30;i++)
{
bytalbum[j] = info[i];
position++;
j++;
}
currentindex = position;
mp3info.album = this.bytetostring(bytalbum);
//獲取年
str = null;
j = 0;
byte[] bytyear = new byte[4];//將年部分讀到一個單獨的數組中
for(i = currentindex;i<currentindex+4;i++)
{
bytyear[j] = info[i];
position++;
j++;
}
currentindex = position;
mp3info.year = this.bytetostring(bytyear);
//獲取注釋
str = null;
j = 0;
byte[] bytcomment = new byte[28];//將注釋部分讀到一個單獨的數組中
for(i = currentindex;i<currentindex+25;i++)
{
bytcomment[j] = info[i];
position++;
j++;
}
currentindex = position;
mp3info.comment = this.bytetostring(bytcomment);
//以下獲取保留位
mp3info.reserved1 = (char)info[++position];
mp3info.reserved2 = (char)info[++position];
mp3info.reserved3 = (char)info[++position];
return mp3info;
}
上面程序用到下面的方法:
/// <summary>
/// 將字節數組轉換成字符串
/// </summary>
/// <param name = "b">字節數組</param>
/// <returns>返回轉換后的字符串</returns>
private string bytetostring(byte[] b)
{
encoding enc = encoding.getencoding("gb2312");
string str = enc.getstring(b);
str = str.substring(0,str.indexof('/0') >= 0 ? str.indexof('/0') : str.length);//去掉無用字符
return str;
}
改名怎么辦呢?我們按(演唱者)歌名 的格式對歌曲進行改名,程序如下:
/// <summary>
/// 更改文件名
/// </summary>
/// <param name="filepath">文件名</param>
/// <returns></returns>
private bool rename(string filepath)
{
if(file.exists(filepath))
{
mp3info mp3info = new mp3info();
mp3info = this.getmp3info(this.getlast128(filepath));//讀出文件信息
mp3info.artist = this.deletenotvalue(mp3info.artist);
mp3info.title = this.deletenotvalue(mp3info.title);
if(mp3info.artist.trim().length==0)
{
mp3info.artist="未命名";
}
if(mp3info.title.trim().length==0)
{
mp3info.title="未知名歌曲";
}
try
{
//更名
file.move(filepath,filepath.substring(0,filepath.tolower().lastindexof("//")).trim() + "//" + "(" + mp3info.artist.trim() + ")" +mp3info.title.trim() + ".mp3");
return true;
}
catch(exception)
{
return false;
}
}
else
{
return false;
}
}
呵,思路就是這樣了,如果有問題或者需要源碼請發郵件至:[email protected]索取。