package cn.qylk.lrc; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collections; import java.util.List; import android.util.Log; /** * @author qylk2012 * */ public class LrcParser { /** * 解析歌词,参数是歌词文件路径 * * @param lrcpath * lrcfile absolute path<br> * @return a lrclist: List<LRCbean> instead of Vector<LRCbean> Since v2.5.6 */ public static List<LRCbean> ParseLrc(File lrcpath) { try { FileInputStream lrcst = new FileInputStream(lrcpath); BufferedReader br = new BufferedReader(new InputStreamReader(lrcst,"GB2312")); String str; int j; int[] starttime = new int[20];// 设置最多支持20条歌词复用,否则将发生异常 List<LRCbean> lrclist = new ArrayList<LRCbean>(100);// 初始默认100条歌词,多数应该够用 while ((str = br.readLine()) != null) { // 逐行读取 int TimeNum = 0; // 时间标签数量 if (str.equals("")) continue;// 抛弃空行 注:br.readLine()遇到空行返回空字符串 j = 0; String str1[] = str.split("\\]"); // 分离对象 for (int i = 0; i < str1.length; i++) { String str2[] = str1[i].split("\\["); // 去除'[' str1[i] = str2[str2.length - 1]; // 抽取出时间 片段 int ms = Timeparse(str1[i]); if (ms != -1) { // 判断是否为时间标签 TimeNum++; // 计数器加1 starttime[j++] = ms; } } // 处理歌词复用的情况 如:[00:16:01][00:11:02]********* for (int i = 0; i < TimeNum; i++) { LRCbean lrc = new LRCbean(); lrc.beginTime = starttime[i]; if (TimeNum < str1.length) { // 如果有歌词正文 lrc.lrcBody = str1[str1.length - 1]; // str1[]中最后一个就是歌词句了。 } else lrc.lrcBody = "***";// 空歌词行,自己加上一句 lrclist.add(lrc); // 装载入歌词表 } } int sum = lrclist.size() - 1; if (sum == -1) return null; for (int i = sum; i > 0; i--)// 必须从歌词最后一句倒着算,这样也可就解决了歌词复用的问题 { int delt = lrclist.get(i).beginTime - lrclist.get(i - 1).beginTime; if (delt < 0) {// 一般歌词复用,前一个时间标签比后一个时间标签大,如[00:16:01][00:11:02]***** lrclist.get(i - 1).lrcBody = lrclist.get(i).lrcBody;// 为复用歌词设置歌词正文,即把[00:16:01]这个标签的歌词正文设为跟[00:11:02]的一样 } } Collections.sort(lrclist); // 将读取的歌词按起始时间排序 ,很重要的一步 int delt = 0; for (int i = 0; i < sum; i++)// 计算每句歌词持续时间 { delt = lrclist.get(i + 1).beginTime - lrclist.get(i).beginTime;// 起始时间差 lrclist.get(i).lineTime = delt; } return lrclist; } catch (Exception e) { e.printStackTrace(); Log.e("QPLAY_ParseLrc", e.toString()); } return null; } /** * 解析时间标签 * * @param string * @return * @throws Exception */ private static int Timeparse(String string) throws NumberFormatException { // String str[] = string.split(":|\\."); // 分离时间:分、秒、毫秒 if (str.length <= 1 || str.length > 3)// 2012-10-12修复为<=1,原为=1,导致当string为"..."报错 return -1;// 歌词时间标签至少有两部分构成 char c = str[0].charAt(0);// 取第一个字符 if (c < '0' || c > '9') return -1; // 判断第一字符是否为规范数字,这里把超过100分钟的音乐歌词也排除了 // 不返回就默认是时间标签了 int m, s, ms = 0; // 转换时间格式 m = Integer.parseInt(str[0]);// 分 s = Integer.parseInt(str[1]);// 秒 if (str.length == 3) {// 一般时间标签分离长度为3:分、秒、毫秒 ms = Integer.parseInt(str[2]);// 如此处理,兼容没有毫秒的歌词文件 如:[00:01]**** if (ms < 100 && ms > 10) ms = ms * 10;// 百分制转化为千分制 else if (ms < 10) ms = ms * 100;// 十分制转化为千分制 } return (m * 60 + s) * 1000 + ms; } }