接著上一篇文章, 上一篇把ndk開發(fā)遍歷手機文件分享了一下。遍歷出來的MP3文件,我需要展示在android的listview里面,想展示的好看一點,結果發(fā)現(xiàn)又是一個坑。
根據(jù)mp3文件,獲取作者啊專輯啊,不難,但是會出現(xiàn)各種亂碼,煩不勝煩。
1,先普及下這個的知識,MP3文件本身是沒有這些信息的,但是很顯然沒有信息,用戶體驗不行,所以在某某年(百度百科ID3)有人就加了一個ID3V1放在MP3文件的后面;再后來因為某某原因,有人把這個升級了,變成ID3V2放在了MP3的前面(當然ID3V1還在的)。所以現(xiàn)在有些文件是V1的,有些文件是V2的,在獲取信息之前要先判斷,是V1,還是V2, 當然還有一些MP3是兩個都不存在的,一般就是我們看到的未知。如下圖

2,然后我們講一下網絡上面的資源
(1),https://sourceforge.net/projects/javamusictag/
這個地址是一個好資源,里面有jar工具包,也有源代碼;
(2),http://www.ulduzsoft.com/2012/07/parsing-id3v2-tags-in-the-mp3-files/
這里面是一個java文件,解析V2的,沒有解析V1。
以上兩個都是需要做修改的才能被我們使用,否則就是要么亂碼,要么不解析。
我們先說第一個資源吧:
(1),這個是比較全面的JAR,還可以寫信息到文件里面去,如果你使用這個jar的時候,獲取ID3V1出現(xiàn)亂碼了,你需要修改的是org.farng.mp3.id3.ID3v1_1或者org.farng.mp3.id3.ID3v1里面的read方法,默認里面是ISO-8859-1不是適合所有人的,比如我就改成了GBK。? ? ? ? ? 如果你使用這個jar來獲取ID3V2,那么就需要對org.farng.mp3.object.AbstractMP3Object這個文件做修改,他里面的readByteArray(byte[] arr, int offset)這個方法解析我的音樂文件,都是亂碼(可能別人可以使用),具體改動是把里面的方法內容替換成以下:
String charset;
int charcode = arr[0];//獲取編碼標志?
if ( charcode == 0 ){
charset = "GBK";
}else if ( charcode == 3 ){
charset = "UTF-8";
}else{
charset = "UTF-16" ;
}
try {
String con = new String(arr, 1, arr.length - 1, charset);//編碼
//這以下都是為了解碼不錯而寫的,沒有依據(jù)
offset--;
if (offset >= con.length()) {
offset = con.length() - 1;
}
if (offset < 0) {
offset = 0;
}
if ((offset == 0) && (con.length() == 0)) {
con = " ";
}
//這以上都是為了解碼不錯而寫的,沒有依據(jù)
readString(con, offset);//jar里面 的方法
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
修改后以后,重新打包成jar,就可以使用這個新的jar了。
(2)如果你使用第二個網絡資源,這個資源只有一個java文件,也比較簡單,只是解析了V2.如果我們需要全面一點,讓他也可以解析V1,就需要對他做改動
這個文件里面有一個parse方法,這個方法里面有一段如下:
if( headerbuf[0] !='I'|| headerbuf[1] !='D'|| headerbuf[2] !='3'){
? ? ? ?file.close();
? ? ? ?returnfalse;
}
這一段是為了判斷是不是V2(如果是V2的話,開頭三個字符應該是ID3,另,V1部分開頭三個字符是TAG),從上面的代碼可以看出,如果不是V2,就直接結束了,而我們想要的是,如果不是V2,我們就再去試試,是不是V1,如果也不是V1,那么我們只好把作者啊專輯啊,都寫成未知了。所以,我們在file.close();前面加一個方法getID3V1(file);
方法內容如下(從網上拷貝的):
private void getID3V1(RandomAccessFile file) {
byte[] buf = new byte[128];// 初始化標簽信息的byte數(shù)組
try {
file.seek(file.length() - 128);// 移動到文件MP3末尾
file.read(buf);// 讀取標簽信息
file.close();// 關閉文件
} catch (FileNotFoundException e) {
e.printStackTrace();
}// 隨機讀寫方式打開MP3文件
catch (IOException e) {
e.printStackTrace();
}
if (buf.length != 128) {// 數(shù)據(jù)長度是否合法
try {
throw new Exception("MP3標簽信息數(shù)據(jù)長度不合法!");
} catch (Exception e) {
e.printStackTrace();
}
}
String tag = "";
try {
tag = new String(buf, 0, 3, "gbk");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
if (!"TAG".equalsIgnoreCase(tag)) {// 標簽頭是否存在
try {
throw new Exception("MP3標簽信息數(shù)據(jù)格式不正確!");
} catch (Exception e) {
e.printStackTrace();
}
}
try {
m_title = new String(buf, 3, 30, "gbk").trim();
m_artist = new String(buf, 33, 30, "gbk").trim();// 歌手名字
m_floder = new String(buf, 63, 30, "gbk").trim();// 專輯名稱
m_tyer = new String(buf, 93, 4, "gbk").trim();// 出品年份
m_comm = new String(buf, 97, 28, "gbk").trim();// 備注信息
System.out.println("作者:" + m_artist);
System.out.println("標題:" + m_title);
System.out.println("專集:" + m_floder);
System.out.println("音軌:" + m_trck);
System.out.println("年代:" + m_tyer);
System.out.println("類型:" + m_tcon);
System.out.println("備注1:" + m_comm);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
當然從我貼的代碼可以看到,我又使用了GBK編碼,這個資源2里面的有一個方法parseTextField里面也有ISO-8859-1,在我這邊,我也改成了GBK,然后可以使用。
總結下,網絡上面的資源其實很多,但是很亂,比如我們想要找一個可以解決編碼問題的資源,你不會那么巧,剛剛好就找到了你想要的,你需要有耐心,慢慢找,一個個的測試,最后你覺得最靠譜的方法,你再去不斷的調試,不斷的修改。最終肯定能把資源變成適合你的資源。
本文和上一篇文章使用的是一個項目
地址:http://download.csdn.net/detail/xiaodousa/9618128
其實這次經歷中有很多不明白的地方,比如,int charcode = arr[0];//獲取編碼標志?
以及offset是否有什么依據(jù),望大神指教
以上