浅谈歌词解析

最近在做一个音乐播放器,遇到的<歌词解析>的问题,也看了网上不少解析歌词的博客,总结一下歌词解析的方式,有什么不对的希望给我提出来,也希望能够帮到需要帮助的人。
创建一个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]我不存在 才意外

其他的怎么创建类啦,在哪里进行解析了,我就不写了···

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值