java解析lrc_java中用正则表达式解析LRC文件
跟著Mars老師
一起寫android中的Mp3播放器
真是受益匪淺
再次感謝老師的無私奉獻
不過其中問題也確實不少
感覺老師的代碼重構做的不夠
其中對LRC文件的解析也弄的比較馬虎
今天特意花了一天的時間
好好研究了正則表達式
也仔細思索了LRC文件到底應該怎么來解析
以下先分析思路
再給出實現代碼
首先
我們應該明白LRC文件的組成
LRC文件本質就是個符合一定格式規范的文本文件
這一點對照XML文件就很好理解了
一個LRC文件的組成
通常由以下幾個部分組成
[ti:約定]-------標題
[ar:周惠]------演唱者
[al:周蕙-精選]-------專輯
[00:26.00]遠處的鐘聲回蕩在雨里--------每句內容由一個時間點和內容組成
同時應該注意到
[02:23.00][00:49.00]一路從泥濘走到了美景---------在每個內容可能出現多個時間點
然后
我們 用一個實體類
LrcInfo
來封裝每個Lrc文件的具體內容
Java代碼
packagejavamzd.mp3player.Info;
importjava.util.HashMap;
/**
*?用來封裝歌詞信息的類
*?@author?Administrator
*
*/
publicclassLrcInfo?{
privateString?title;//歌曲名
privateString?singer;//演唱者
privateString?album;//專輯
privateHashMap?infos;//保存歌詞信息和時間點一一對應的Map
//以下為getter()??setter()
}
3.讀入Lrc文件,開始逐行解析
解析步驟:
1.讀入文件
2.封裝為BufferedReader對象
3.調用readline()方法逐行讀取數據,得到String str
4.用parser()方法解析每一條具體的String語句
5.每句解析完后,將得到的內容在LrcInfo對象中進行設置
Java代碼
importjava.io.BufferedReader;
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.FileNotFoundException;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.InputStreamReader;
importjava.util.HashMap;
importjava.util.Map;
importjava.util.regex.Matcher;
importjava.util.regex.Pattern;
/**
*?此類用來解析LRC文件?將解析完整的LRC文件放入一個LrcInfo對象中?并且返回這個LrcInfo對象s?author:java_mzd
*/
publicclassLrcParser?{
privateLrcInfo?lrcinfo?=newLrcInfo();
privatelongcurrentTime?=0;//存放臨時時間
privateString?currentContent?=null;//存放臨時歌詞
privateMap?maps?=newHashMap();//用戶保存所有的歌詞和時間點信息間的映射關系的Map
/**
*?根據文件路徑,讀取文件,返回一個輸入流
*
*?@param?path
*????????????路徑
*?@return?輸入流
*?@throws?FileNotFoundException
*/
privateInputStream?readLrcFile(String?path)throwsFileNotFoundException?{
File?f?=?newFile(path);
InputStream?ins?=?newFileInputStream(f);
returnins;
}
publicLrcInfo?parser(String?path)throwsException?{
InputStream?in?=?readLrcFile(path);
lrcinfo?=?parser(in);
returnlrcinfo;
}
/**
*?將輸入流中的信息解析,返回一個LrcInfo對象
*
*?@param?inputStream
*????????????輸入流
*?@return?解析好的LrcInfo對象
*?@throws?IOException
*/
publicLrcInfo?parser(InputStream?inputStream)throwsIOException?{
//?三層包裝
InputStreamReader?inr?=?newInputStreamReader(inputStream);
BufferedReader?reader?=?newBufferedReader(inr);
//?一行一行的讀,每讀一行,解析一行
String?line?=?null;
while((line?=?reader.readLine())?!=null)?{
parserLine(line);
}
//?全部解析完后,設置info
lrcinfo.setInfos(maps);
returnlrcinfo;
}
/**
*?利用正則表達式解析每行具體語句
*?并在解析完該語句后,將解析出來的信息設置在LrcInfo對象中
*
*?@param?str
*/
privatevoidparserLine(String?str)?{
//?取得歌曲名信息
if(str.startsWith("[ti:"))?{
String?title?=?str.substring(4,?str.length()?-1);
System.out.println("title--->"+?title);
lrcinfo.setTitle(title);
}//?取得歌手信息
elseif(str.startsWith("[ar:"))?{
String?singer?=?str.substring(4,?str.length()?-1);
System.out.println("singer--->"+?singer);
lrcinfo.setSinger(singer);
}//?取得專輯信息
elseif(str.startsWith("[al:"))?{
String?album?=?str.substring(4,?str.length()?-1);
System.out.println("album--->"+?album);
lrcinfo.setAlbum(album);
}//?通過正則取得每句歌詞信息
else{
//?設置正則規則
String?reg?=?"\\[(\\d{2}:\\d{2}\\.\\d{2})\\]";
//?編譯
Pattern?pattern?=?Pattern.compile(reg);
Matcher?matcher?=?pattern.matcher(str);
//?如果存在匹配項,則執行以下操作
while(matcher.find())?{
//?得到匹配的所有內容
String?msg?=?matcher.group();
//?得到這個匹配項開始的索引
intstart?=?matcher.start();
//?得到這個匹配項結束的索引
intend?=?matcher.end();
//?得到這個匹配項中的組數
intgroupCount?=?matcher.groupCount();
//?得到每個組中內容
for(inti?=0;?i?<=?groupCount;?i++)?{
String?timeStr?=?matcher.group(i);
if(i?==1)?{
//?將第二組中的內容設置為當前的一個時間點
currentTime?=?strToLong(timeStr);
}
}
//?得到時間點后的內容
String[]?content?=?pattern.split(str);
//?輸出數組內容
for(inti?=0;?i?
if(i?==?content.length?-1)?{
//?將內容設置為當前內容
currentContent?=?content[i];
}
}
//?設置時間點和內容的映射
maps.put(currentTime,?currentContent);
System.out.println("put---currentTime--->"+?currentTime
+?"----currentContent---->"+?currentContent);
}
}
}
/**
*?將解析得到的表示時間的字符轉化為Long型
*
*?@param?group
*????????????字符形式的時間點
*?@return?Long形式的時間
*/
privatelongstrToLong(String?timeStr)?{
//?因為給如的字符串的時間格式為XX:XX.XX,返回的long要求是以毫秒為單位
//?1:使用:分割?2:使用.分割
String[]?s?=?timeStr.split(":");
intmin?=?Integer.parseInt(s[0]);
String[]?ss?=?s[1].split("\\.");
intsec?=?Integer.parseInt(ss[0]);
intmill?=?Integer.parseInt(ss[1]);
returnmin?*60*1000+?sec?*1000+?mill?*10;
}
publicstaticvoidmain(String[]?args)?{
LrcParser?lp?=?newLrcParser();
try{
lp.parser("G:\\WebRoot\\a1.lrc");
}?catch(Exception?e)?{
System.out.println("parser?erro");
e.printStackTrace();
}
}
}
以上代碼難度都不大
個人覺得
正則表達式其實并不難
只是因為有很多不規則符號堆疊在一起
讓我們直觀的很難理解
掌握符號規則后
還是挺好用的
正則表達在JAVA中都被封裝在
regex包下面
主要是Pattern類與Matcher類
其實我個人在掌握了正則的基本概念后
用JAVA寫這個代碼卻花了不少時間
主要是對這兩個對象中的一些方法理解錯誤
以下簡單總結下
兩個類中易理解錯的方法
Matcher對象中
matcher()方法是匹配整個字符串
lookingat()是匹配字符串的開頭
find()是查找字符串中能否匹配
使用find()方法
得到一個字符串中的匹配后
matcher.start()得到這個匹配的startIndex
matcher.end()得到這個匹配的endIndex
matcher.group()能得到滿足匹配的全部內容(最大的一個組)
matcher.groupCount()能得到當前匹配中的組數------(在正則中用()包圍起來的一個部分算一個單獨的組)
marcher.group(i) 得到指定的某個組的內容
又通過matcher.find()
我們可能在某一行可以得到多個匹配結果
每當調用一次matcher.find()
當前匹配對象就自動換為下個匹配成功對象
要遍歷所有匹配結果
Java代碼
//遍歷每個匹配成功對象
while?(matcher.find())?{
?????????????????????//對每一個匹配對象的操作
????????????????//?得到匹配的所有內容
String?msg?=?matcher.group();
//?得到這個匹配項開始的索引
intstart?=?matcher.start();
//?得到這個匹配項結束的索引
intend?=?matcher.end();
//?得到這個匹配項中的組數
intgroupCount?=?matcher.groupCount();
//?得到每個組中內容
for(inti?=0;?i?<=?groupCount;?i++)?{
String?timeStr?=?matcher.group(i);
if(i?==1)?{
//?將第二組中的內容設置為當前的一個時間點
currentTime?=?strToLong(timeStr);
}
}
//?得到時間點后的內容
String[]?content?=?pattern.split(str);
//?輸出數組內容
for(inti?=0;?i?
if(i?==?content.length?-1)?{
//?將內容設置為當前內容
currentContent?=?content[i];
}
} http://java-mzd.iteye.com/blog/811374
總結
以上是生活随笔為你收集整理的java解析lrc_java中用正则表达式解析LRC文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java xmn xms_JVM调优总结
- 下一篇: 怎么卸载旧版本java_卸载旧的java