最近在做一个音乐播放器,遇到的<歌词解析>的问题,也看了网上不少解析歌词的博客,总结一下歌词解析的方式,有什么不对的希望给我提出来,也希望能够帮到需要帮助的人。
创建一个lyric的歌词类
/**
* 作者:zxn
* 作用:封装歌词信息
*/
public class Lyric {
/**
* 歌词内容
*/
private String content;
/**
* 时间戳
*/
private long timePoint;
/**
* 当前行高亮显示的时间
*/
private long sleepTime;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public long getTimePoint() {
return timePoint;
}
public void setTimePoint(long timePoint) {
this.timePoint = timePoint;
}
public long getSleepTime() {
return sleepTime;
}
public void setSleepTime(long sleepTime) {
this.sleepTime = sleepTime;
}
@Override
public String toString() {
return "Lyric{" +
"content='" + content + '\'' +
", timePoint=" + timePoint +
", sleepTime=" + sleepTime +
'}';
}
}
//创建一个歌词解析的类
/**
* 作者:zxn
* 作用:解析歌词工具类
*/
public class LyricUtils {
/**
* 得到解析好的歌词列表
* @return
*/
public ArrayList<Lyric> getLyrics() {
return lyrics;
}
//创建一个歌词
private ArrayList<Lyric> lyrics;
/**
* 读取歌词文件
* @param file /mnt/scard/Music/丑八怪.lrc
public void readLyricFile(File file){
if(file == null || !file.exists()){
lyrics = null;
}else{
//歌词文件存在
//1.解析歌词 一行的读取-解析
lyrics = new ArrayList<>();
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file),getCharset(file)));
//读取每一行歌词的字符串
String line = "";
while ((line = reader.readLine())!= null){
line = parsedLyric(line);//
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
//2.通过事件戳对每一句歌词进行排序
Collections.sort(lyrics, new Comparator<Lyric>() {
@Override
public int compare(Lyric lhs, Lyric rhs) {
if(lhs.getTimePoint() < rhs.getTimePoint()){
return -1;
}else if(lhs.getTimePoint() > rhs.getTimePoint()){
return 1;
}else{
return 0;
}
}
});
//3.计算每句高亮显示的时间,就是sleepTime
for(int i=0;i<lyrics.size();i++){
Lyric oneLyric = lyrics.get(i);
if(i+1 < lyrics.size()){
Lyric twoLyric = lyrics.get(i+1);
oneLyric.setSleepTime(twoLyric.getTimePoint()-oneLyric.getTimePoint());
}
}
}
}
/**
* 判断文件编码
* @param file 文件
* @return 编码:GBK,UTF-8,UTF-16LE
*/
public String getCharset(File file) {
String charset = "GBK";
byte[] first3Bytes = new byte[3];
try {
boolean checked = false;
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(file));
bis.mark(0);
int read = bis.read(first3Bytes, 0, 3);
if (read == -1)
return charset;
if (first3Bytes[0] == (byte) 0xFF && first3Bytes[1] == (byte) 0xFE) {
charset = "UTF-16LE";
checked = true;
} else if (first3Bytes[0] == (byte) 0xFE
&& first3Bytes[1] == (byte) 0xFF) {
charset = "UTF-16BE";
checked = true;
} else if (first3Bytes[0] == (byte) 0xEF
&& first3Bytes[1] == (byte) 0xBB
&& first3Bytes[2] == (byte) 0xBF) {
charset = "UTF-8";
checked = true;
}
bis.reset();
if (!checked) {
int loc = 0;
while ((read = bis.read()) != -1) {
loc++;
if (read >= 0xF0)
break;
if (0x80 <= read && read <= 0xBF)
break;
if (0xC0 <= read && read <= 0xDF) {
read = bis.read();
if (0x80 <= read && read <= 0xBF)
continue;
else
break;
} else if (0xE0 <= read && read <= 0xEF) {
read = bis.read();
if (0x80 <= read && read <= 0xBF) {
read = bis.read();
if (0x80 <= read && read <= 0xBF) {
charset = "UTF-8";
break;
} else
break;
} else
break;
}
}
}
bis.close();
} catch (Exception e) {
e.printStackTrace();
}
return charset;
}
/**
* 解析一句歌词
* @param line [00:19.97]如果世界漆黑 其实我很美
* @return
*/
private String parsedLyric(String line) {
indexOf第一次出现[的位置
int pos1 = line.indexOf("[");//0,如果没有返回-1
int pos2 = line.indexOf("]");//9,如果没有返回-1
if(pos1 ==0 && pos2 != -1){//肯定是有一句歌词
//装时间
long[] times = new long[getCountTag(line)];
String strTime =line.substring(pos1+1,pos2) ;//这个字符串是这个00:19.97
times[0] = strTime2LongTime(strTime);//将字符串转化成Long类型的时间,存入时间的数组中
//一行有多个时间点的情况,比如[][]
String content = line;
int i = 1;
while (pos1 ==0 && pos2 != -1){
content = content.substring(pos2 + 1);
pos1 = content.indexOf("[");//0/-1
pos2 = content.indexOf("]");//9//-1
if(pos2 != -1 ){
strTime = content.substring(pos1 + 1, pos2);
times[i] = strTime2LongTime(strTime);
if(times[i] == -1){
return "";
}
i++;
}
}
//创建歌词对象,给其设置内容,时间戳
Lyric lyric = new Lyric();
//把时间数组和文本关联起来,并且加入到集合中
for(int j = 0;j < times.length;j++){
if(times[j] !=0){//有时间戳
//把每一句歌词的内容和时间戳都设置到lyric中!!
lyric.setContent(content);
lyric.setTimePoint(times[j]);
//将每一句歌词添加到集合中
lyrics.add(lyric);
lyric = new Lyric();
}
}
return content;//如果世界漆黑 其实我很美
}
return "";
}
/**
* 把String类型是时间转换成long类型
* @param strTime 00:19.97
* @return
*/
private long strTime2LongTime(String strTime) {
long result = -1;
try{
//这样看来还是必须要学一些算法的,我是个小菜鸟啊
//1.把00:19.97按照:切割成00和19.97
String[] s1 = strTime.split(":");
//2.把19.97按照.切割成19和97,split切割!!!
String[] s2 = s1[1].split("\\.");
//1.分
long min = Long.parseLong(s1[0]);
//2.秒
long second = Long.parseLong(s2[0]);
//3.毫秒
long mil = Long.parseLong(s2[1]);
//我看了别人的博客,后边的时间是不乘以10的,但后来发现不对,必须乘以10
result = min * 60 * 1000 + second * 1000 + mil*10;
}catch (Exception e){
e.printStackTrace();
result = -1;
}
return result;
}
/**
* 判断有多少句歌词
* @param line
* @return
*/
private int getCountTag(String line) {
int result = -1;
String [] left = line.split("\\[");
String [] right = line.split("\\]");
if(left.length==0 && right.length ==0){
result = 1;
}else if(left.length > right.length){
result = left.length;
}else{
result = right.length;
}
return result;
}
}
//很喜欢薛的歌,所以,用的这个,不用管这边是什么ver\ti等什么的,直接解析就ok!!
[ver:v1.0]
[ti:626+]
[00:00.58]丑八怪 - 薛之谦
[00:02.90]作词 : 甘世佳
[00:05.34]作曲 : 李荣浩
[00:19.97]如果世界漆黑 其实我很美
[00:23.46]在爱情里面进退 最多被消费
[00:27.33]无关痛痒的是非
[00:29.01]又怎么不对 无所谓
[00:35.30]如果像你一样 总有人赞美
[00:38.94]围绕着我的卑微 也许能消退
[00:42.92]其实我并不在意 有很多机会
[00:46.02]像巨人一样的无畏
[00:49.10]放纵我心里的鬼
[00:50.57]可是我不配
[00:54.18]丑八怪 能否别把灯打开
[01:01.59]我要的爱 出没在漆黑一片的舞台
[01:09.20]丑八怪 在这暧昧的时代
[01:17.18]我的存在 像意外
[01:37.42]有人用一滴泪 会红颜祸水
[01:41.07]有人丢掉称谓 什么也不会
[01:44.81]只要你足够虚伪
[01:46.40]就不怕魔鬼 对不对
[01:52.74]如果剧本写好 谁比谁高贵
[01:56.42]我只能沉默以对 美丽本无罪
[02:00.13]当欲望开始贪杯 有更多机会
[02:03.45]像尘埃一样的无畏
[02:06.54]化成灰谁认得谁管他配不配
[02:11.59]丑八怪 能否别把灯打开
[02:19.09]我要的爱 出没在漆黑一片的舞台
[02:26.59]丑八怪 在这暧昧的时代
[02:34.61]我的存在 不意外
[03:01.45]丑八怪 其实见多就不怪
[03:09.45]放肆去high 用力踩
[03:13.90]那不堪一击的洁白
[03:16.88]丑八怪 这是我们的时代
[03:24.87]我不存在 才意外
其他的怎么创建类啦,在哪里进行解析了,我就不写了···