跟着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文件相关推荐

  1. java xml stax_Java StAX解析器示例以读取XML文件

    java xml stax We can use Java StAX parser to read XML file. Java Streaming API for XML (Java StAX) p ...

  2. JAVA SE 进阶篇 C3 解析XML文件,做一个jar工具包

    文章目录 P1 XML文件 1 XML文件概述 (1) 可扩展标记语言:XML (2) XML文件的书写规则和语法要求 2 创建一个XML文件 P2 解析给定的XML文件 1 XML解析器和W3C 2 ...

  3. 分布式.RPC-WebService入门案例(java实现,注解实现,xsd文件解析,wsdl文件解析)

     系列博文: 分布式.RPC调用-RMI & Hessian框架_闲猫的博客-CSDN博客 分布式.RPC-WebService三要素,三个规范, Soap协议_闲猫的博客-CSDN博客 分布 ...

  4. Java I/O读取和解析.emp文件示例

    Java I/O读取和解析.emp文件示例 1.使用到的知识点 2.示例1 2.1存储几个员工数据到不同的文件 2.1.1题目要求 2.1.2相关代码 2.1.3结果展示 2.2读取存储数据的文件 2 ...

  5. tinyxml 读取文本节点_c++中用TINYXML解析XML文件

    TinyXML介绍 最近做一个负载均衡的小项目,需要解析xml配置文件,用到了TinyXML,感觉使用起来很容易,给出一个使用TinyXML进行XML解析的简单例子,很多复杂的应用都可以基于本例子的方 ...

  6. java stax xml_在JDK6.0中用StAX解析XML

    摘要 J2EE/XML开发人员一般都用DOM(Document Object Model,文档对象模型)API或者(SAX Simple API for XML)来解析XML文件.这些API各有利弊. ...

  7. ipv6正则表达式 java,用正则表达式解析IPv4跟IPv6地址字符串

    用正则表达式解析IPv4和IPv6地址字符串 以下是经过我的.net C# 代码百般测试的,绝对经得住考验! IPv4[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9] ...

  8. java歌词解析器_JAVA 正则解析歌词

    //目录结构 //来看一下歌词内容 [00:00.00]领袖音乐分享平台 http://www.kugou.com [00:02.31]Pretty boy-M2M 英俊男孩 JY93653制作 [0 ...

  9. 【面试资料】 Java中高级核心面试知识解析

    [面试资料] Java中高级核心面试知识解析 一.Java (一). 基础 (二). 容器 (三). 并发 (四). JVM 二.网络 (一). 计算机网络知识 (二). HTTPS中的TLS 三.L ...

最新文章

  1. 黑马程序员--java基础--其他对象
  2. Django - 分页器
  3. 乡村振兴种业使命-丰收节交易会·张桃林:种业谋定格局
  4. xa协议 mysql_分布式事务XA实现数据一致性的协议与原理
  5. ashx和asmx的HttpContext
  6. 树莓派3B+学习笔记:4、查看GPIO
  7. jQuery原理第一天
  8. 计算机naf类型是什么,计算机系统结构课后习题答案
  9. 联想笔记本prtsc不能截图_Win10系统下怎么截屏
  10. 斐波那契堆python实现——Fibonacci Heaps
  11. 如何将pdf转换成jpg图片格式
  12. js报错未定义的ajax,ReactJS和AJAX未捕获TypeError:无法读取未定义的属性'错误'
  13. samtools faid产生的.fai文件详解
  14. [管理新思维]社会化管理和开放式创新|裂变式创业
  15. 张一鸣:年轻人一定要懂得延迟满足
  16. 百度搜索结果页面的参数 提示词输入搜索框方式(rsv_sug5)
  17. 命令点亮硬盘灯_【硬盘无法识别怎么办?】
  18. LZO基本介绍与调试总结
  19. chi2inv函数 matlab_matlab函数与指令大全 a——h (转载)
  20. 【Python数据类型展示】

热门文章

  1. C++ 可以把变量当成函数用~~
  2. repne scasb 内联实现 strlen
  3. 以管理员权限来进行解压操作
  4. 006 技能数组分析和代码编写
  5. 春季每日一题2022 Week 2 【完结】
  6. 力扣 136. 只出现一次的数字 【异或运算】
  7. jQuery的祖先遍历
  8. C语言外部函数与内部函数
  9. python 求连线相似度_Python分析《都挺好》中的人物关系,苏大强与蔡根花是真爱?...
  10. 眼图在通信系统中有什么意义_解读CRM系统在企业中有什么作用