• Java使用正则表达式解析LRC歌词文件


    LRC歌词是一种应用广泛的歌词文件,各主流播放器都支持。

    lrc歌词文本中含有两类标签:

    1、标识标签(ID-tags)

    [ar:艺人名]
    [ti:曲名]
    [al:专辑名]
    [by:编者(指编辑LRC歌词的人)]
    [offset:时间补偿值] 其单位是毫秒,正值表示整体提前,负值相反

    2、 时间标签(Time-tag)

    标准格式: [分钟:秒.毫秒] 歌词

    例:[01:15.62]

    在这里为了简便我只是解析了时间标签,对其进行解析时使用到了正则表达式:

    正则表达式语法参考:http://www.cnblogs.com/wuqianling/p/5686139.html

    示例歌词:

    [ar:胡彦斌]
    [ti:月光]
    [00:00.86]月光(秦时明月主题曲)
    [00:06.31]歌手 胡彦斌
    [00:08.68]作词 林文炫
    [00:10.49]作曲 胡彦斌
    [00:20.11]月光色
    [00:22.30]女子香
    [00:24.51]泪断剑
    [00:26.70]情多长
    [00:28.95]有多痛
    [00:30.97]无字想
    [00:33.35]忘了你
    [00:39.43]孤单魂
    [00:41.51]随风荡
    [00:43.57]谁去笑
    [00:45.87]痴情郎
    [00:48.03]这红尘的战场
    [00:52.95]千军万马有谁能称王
    [01:01.69]过情关
    [01:06.00]谁敢闯
    [01:10.42]望明月
    [01:15.62]心悲凉
    [01:19.13]千古恨
    [01:23.45]轮回尝
    [01:27.76]眼一闭
    [01:32.71]谁最狂
    [01:38.90]这世道的无常
    [01:43.23]注定敢爱的人一生伤
    [02:07.33]月光色
    [02:09.20]女子香
    [02:11.49]泪断剑
    [02:13.58]情多长
    [02:15.80]有多痛
    [02:17.87]无字想
    [02:20.23]忘了你
    [02:26.21]孤单魂
    [02:28.20]随风荡
    [02:30.56]谁去笑
    [02:32.64]痴情郎
    [02:34.94]这红尘的战场
    [02:39.70]千军万马有谁能称王
    [02:48.65]过情关
    [02:52.66]谁敢闯
    [02:57.34]望明月
    [03:02.44]心悲凉
    [03:05.97]千古恨
    [03:09.99]轮回尝
    [03:14.67]眼一闭
    [03:19.95]谁最狂
    [03:30.06]过情关
    [03:34.34]谁敢闯
    [03:38.78]望明月
    [03:43.92]心悲凉
    [03:47.58]千古恨
    [03:51.50]轮回尝
    [03:55.96]眼一闭
    [04:01.51]谁最狂
    [04:07.21]这世道的无常
    [04:21.34]注定敢爱的人一生伤
    View Lyric

    Java源代码:

      1 import java.io.BufferedReader;
      2 import java.io.File;
      3 import java.io.FileInputStream;
      4 import java.io.InputStreamReader;
      5 import java.util.ArrayList;
      6 import java.util.HashMap;
      7 import java.util.List;
      8 import java.util.Map;
      9 import java.util.Map.Entry;
     10 import java.util.regex.Matcher;
     11 import java.util.regex.Pattern;
     12 
     13 public class TestLRC {
     14 
     15     public static void main(String[] args) {
     16         String path = "D:\a.lrc"; // 歌词文件路径
     17         TestLRC lrc = new TestLRC();
     18         List<Map<Long, String>> list = lrc.parse(path);
     19         lrc.printLrc(list);
     20     }
     21 
     22     /**
     23      * 解析LRC歌词文件
     24      * 
     25      * @param path
     26      *            lrc文件路径
     27      * @return
     28      */
     29     private List<Map<Long, String>> parse(String path) {
     30         // 存储所有歌词信息的容器
     31         List<Map<Long, String>> list = new ArrayList<Map<Long, String>>();
     32         try {
     33             // String encoding = "utf-8"; // 字符编码,若与歌词文件编码不符将会出现乱码
     34             String encoding = "GBK";
     35             File file = new File(path);
     36             if (file.isFile() && file.exists()) { // 判断文件是否存在
     37                 InputStreamReader read = new InputStreamReader(
     38                         new FileInputStream(file), encoding);
     39                 BufferedReader bufferedReader = new BufferedReader(read);
     40                 String regex = "\[(\d{1,2}):(\d{1,2}).(\d{1,2})\]"; // 正则表达式
     41                 Pattern pattern = Pattern.compile(regex); // 创建 Pattern 对象
     42                 String lineStr = null; // 每次读取一行字符串
     43                 while ((lineStr = bufferedReader.readLine()) != null) {
     44                     Matcher matcher = pattern.matcher(lineStr);
     45                     while (matcher.find()) {
     46                         // 用于存储当前时间和文字信息的容器
     47                         Map<Long, String> map = new HashMap<Long, String>();
     48                         // System.out.println(m.group(0)); // 例:[02:34.94]
     49                         // [02:34.94] ----对应---> [分钟:秒.毫秒]
     50                         String min = matcher.group(1); // 分钟
     51                         String sec = matcher.group(2); //
     52                         String mill = matcher.group(3); // 毫秒,注意这里其实还要乘以10
     53                         long time = getLongTime(min, sec, mill + "0");
     54                         // 获取当前时间的歌词信息
     55                         String text = lineStr.substring(matcher.end());
     56                         map.put(time, text); // 添加到容器中
     57                         list.add(map);
     58                     }
     59                 }
     60                 read.close();
     61                 return list;
     62             } else {
     63                 System.out.println("找不到指定的文件:" + path);
     64             }
     65         } catch (Exception e) {
     66             System.out.println("读取文件出错!");
     67             e.printStackTrace();
     68         }
     69         return null;
     70     }
     71 
     72     /**
     73      * 将以字符串形式给定的分钟、秒钟、毫秒转换成一个以毫秒为单位的long型数
     74      * 
     75      * @param min
     76      *            分钟
     77      * @param sec
     78      *            秒钟
     79      * @param mill
     80      *            毫秒
     81      * @return
     82      */
     83     private long getLongTime(String min, String sec, String mill) {
     84         // 转成整型
     85         int m = Integer.parseInt(min);
     86         int s = Integer.parseInt(sec);
     87         int ms = Integer.parseInt(mill);
     88 
     89         if (s >= 60) {
     90             System.out.println("警告: 出现了一个时间不正确的项 --> [" + min + ":" + sec + "."
     91                     + mill.substring(0, 2) + "]");
     92         }
     93         // 组合成一个长整型表示的以毫秒为单位的时间
     94         long time = m * 60 * 1000 + s * 1000 + ms;
     95         return time;
     96     }
     97 
     98     /**
     99      * 打印歌词信息
    100      */
    101     private void printLrc(List<Map<Long, String>> list) {
    102         if (list == null || list.isEmpty()) {
    103             System.out.println("没有任何歌词信息!");
    104         } else {
    105             for (Map<Long, String> map : list) {
    106                 for (Entry<Long, String> entry : map.entrySet()) {
    107                     System.out.println("时间:" + entry.getKey() + "  	歌词:"
    108                             + entry.getValue());
    109                 }
    110             }
    111         }
    112     }
    113 }
    114  

    解析结果:

  • 相关阅读:
    JDBC连接MySQL数据库及演示样例
    Devstack: A copy of worked local.conf I&#39;m sharing with you.
    jQuery Easy UI Droppable(放置)组件
    指针
    “cvSnakeImage”: 找不到标识符
    按键控制电机显示速度
    验证(Verification)与确认(Validation)的差别
    转换流--OutputStreamWriter类与InputStreamReader类
    特征选择方法之信息增益
    Angular和jQuery的ajax请求的差别
  • 原文地址:https://www.cnblogs.com/wuqianling/p/5656761.html
Copyright © 2020-2023  润新知