`

java 歌词解析

 
阅读更多
package data;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class Statement{
	private double time=0.0;								//时间, 单位为s, 精确到0.01s
	private String lyric="";								//歌词

	/*
	 * 获取时间
	 */
	public double getTime() {
		return time;
	}
	/*
	 * 设置时间
	 * time: 被设置成的时间
	 */
	public void setTime(double time) {
		this.time = time;
	}
	/*
	 * 设置时间
	 * time: 被设置成的时间字符串, 格式为mm:ss.ms
	 */
	public void setTime(String time) {
		String str[] = time.split(":|\\.");
		this.time = Integer.parseInt(str[0])*60+Integer.parseInt(str[1])+Integer.parseInt(str[2])*0.01;
	}
	/*
	 * 获取歌词
	 */
	public String getLyric() {
		return lyric;
	}
	/*
	 * 设置歌词
	 */
	public void setLyric(String lyric) {
		this.lyric = lyric;
	}
	/*
	 * 打印歌词
	 */
	public void printLyric()
	{
		System.out.println(time+": "+lyric);
	}
}

public class LrcData {
	BufferedReader bufferReader = null;							//读取文件实例
	public String title = "";									//歌曲题目
	public String artist = "";									//演唱者
	public String album = "";									//专辑
	public String lrcMaker = "";								//歌词制作者
	Vector<Statement> statements = new Vector<Statement>();		//歌词
	
	/* 
	 * 实例化一个歌词数据. 歌词数据信息由指定的文件提供. 
	 * fileName: 指定的歌词文件. 
	 */
	public LrcData(String fileName) throws IOException{
		FileInputStream file = new FileInputStream(fileName);
		bufferReader = new BufferedReader(new InputStreamReader(file, "GB2312"));
		
		//将文件数据读入内存
		readData();
	}
	
	/*
	 * 读取文件中数据至内存. 
	 */
	public void readData() throws IOException{
		statements.clear();
		String strLine;
		//循环读入所有行
		while(null != (strLine = bufferReader.readLine()))
		{
			//判断该行是否为空行
			if("".equals(strLine.trim()))
			{
				continue;
			}
			//判断该行数据是否表示歌名
			if(null == title || "".equals(title.trim()))
			{
				Pattern pattern = Pattern.compile("\\[ti:(.+?)\\]");
				Matcher matcher = pattern.matcher(strLine);
				if(matcher.find())
				{
					title=matcher.group(1);
					continue;
				}
			}
			//判断该行数据是否表示演唱者
			if(null == artist || "".equals(artist.trim()))
			{
				Pattern pattern = Pattern.compile("\\[ar:(.+?)\\]");
				Matcher matcher = pattern.matcher(strLine);
				if(matcher.find())
				{
					artist=matcher.group(1);
					continue;
				}
			}
			//判断该行数据是否表示专辑
			if(null == album || "".equals(album.trim()))
			{
				Pattern pattern = Pattern.compile("\\[al:(.+?)\\]");
				Matcher matcher = pattern.matcher(strLine);
				if(matcher.find())
				{
					album=matcher.group(1);
					continue;
				}
			}
			//判断该行数据是否表示歌词制作者
			if(null == lrcMaker || "".equals(lrcMaker.trim()))
			{
				Pattern pattern = Pattern.compile("\\[by:(.+?)\\]");
				Matcher matcher = pattern.matcher(strLine);
				if(matcher.find())
				{
					lrcMaker=matcher.group(1);
					continue;
				}
			}
			//读取并分析歌词
			int timeNum=0;										//本行含时间个数
			String str[] = strLine.split("\\]");				//以]分隔
			for(int i=0; i<str.length; ++i)
			{
				String str2[] = str[i].split("\\[");			//以[分隔
				str[i] = str2[str2.length-1];
				if(isTime(str[i])){
					++timeNum;
				}
			}
			for(int i=0; i<timeNum;++i)					//处理歌词复用的情况
			{
				Statement sm = new Statement();
				sm.setTime(str[i]);
				if(timeNum<str.length)					//如果有歌词
				{
					sm.setLyric(str[str.length-1]);
				}
				statements.add(sm);
			}
//			if(1==str.length)									//处理没有歌词的情况
//			{
//				Statement sm = new Statement();
//				sm.setTime(str[0]);
//				sm.setLyric("");
//				statements.add(sm);
//			}
		}
		
		//将读取的歌词按时间排序
		sortLyric();
	}
	/*
	 * 判断给定的字符串是否表示时间. 
	 */
	public boolean isTime(String string)
	{
		String str[] = string.split(":|\\.");
		if(3!=str.length)
		{
			return false;
		}
		try{
			for(int i=0;i<str.length;++i)
			{
				Integer.parseInt(str[i]);
			}
		}
		catch(NumberFormatException e)
		{
			return false;
		}
		return true;
	}
	/*
	 * 将读取的歌词按时间排序. 
	 */
	public void sortLyric()
	{
		for(int i=0;i<statements.size()-1;++i)
		{
			int index=i;
			double delta=Double.MAX_VALUE;
			boolean moveFlag = false;
			for(int j=i+1;j<statements.size();++j)
			{
				double sub;
				if(0>=(sub=statements.get(i).getTime()-statements.get(j).getTime()))
				{
					continue;
				}
				moveFlag=true;
				if(sub<delta)
				{
					delta=sub;
					index=j+1;
				}
			}
			if(moveFlag)
			{
				statements.add(index, statements.elementAt(i));
				statements.remove(i);
				--i;
			}
		}
	}

	/*
	 * 打印整个歌词文件
	 */
	public void printLrcDate()
	{
		System.out.println("歌曲名: "+title);
		System.out.println("演唱者: "+artist);
		System.out.println("专辑名: "+album);
		System.out.println("歌词制作: "+lrcMaker);
		for(int i=0;i<statements.size();++i)
		{
			statements.elementAt(i).printLyric();
		}
	}
	
	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		/*
		 * 测试"[", "]"的ASCII码
		 */
//		{
//			char a='[', b = ']';
//			int na = (int)a;
//			int nb = (int)b;
//			System.out.println("a="+na+", b="+nb+"\n");
//		}
		/*
		 * 测试匹配[]. 注: [应用\[表示. 同理]应用\]表示. 
		 */
//		{
//			String strLyric = "[02:13.41][02:13.42][02:13.43]错误的泪不想哭却硬要留住";
//			String str[] = strLyric.split("\\]");
//			for(int i=0; i<str.length; ++i)
//			{
//				String str2[] = str[i].split("\\[");
//				str[i] = str2[str2.length-1];
//				System.out.println(str[i]+" ");
//			}
//		}
		/*
		 * 测试匹配[ti:]. 注: [应用\[表示. 同理]应用\]表示. 
		 */
//		{
//			String strLyric = "[ti:Forget]";
//			Pattern pattern = Pattern.compile("\\[ti:(.+?)\\]");
//			Matcher matcher = pattern.matcher(strLyric);
//			if(matcher.find())
//			  System.out.println(matcher.group(1));
//		}
		/*
		 * 测试排序算法
		 */
//		{
//			Vector<Double> vect=new Vector<Double>();
//			vect.add(5.0);
//			vect.add(28.0);
//			vect.add(37.0);
//			vect.add(10.0);
//			vect.add(25.0);
//			vect.add(40.0);
//			vect.add(27.0);
//			vect.add(35.0);
//			vect.add(70.0);
//			vect.add(99.0);
//			vect.add(100.0);
//			
//			for(int i=0;i<vect.size();++i)
//			{
//				System.out.println(vect.elementAt(i));
//			}
//			
//			for(int i=0;i<vect.size()-1;++i)
//			{
//				int index=i;
//				double delta=Double.MAX_VALUE;
//				boolean moveFlag = false;
//				for(int j=i+1;j<vect.size();++j)
//				{
//					double sub;
//					if(0>=(sub=vect.get(i)-vect.get(j)))
//					{
//						continue;
//					}
//					moveFlag=true;
//					if(sub<delta)
//					{
//						delta=sub;
//						index=j+1;
//					}
//				}
//				if(moveFlag)
//				{
//					vect.add(index, vect.elementAt(i));
//					vect.remove(i);	
//					System.out.println("第"+i);
//					--i;
//				}
//			}
//
//			System.out.println("排序后");
//			for(int i=0;i<vect.size();++i)
//			{
//				System.out.println(vect.elementAt(i));
//			}
//		}
		
		/*
		 * 测试由字符串转化为双精度时间
		 */
//		{
//			String stime="02:03.09";
//			String str[] = stime.split(":|\\.");
//			for(int i=0;i<str.length;++i)
//			{
//				System.out.print("时间"+str[i]+":");
//			}
//			double dtime = Integer.parseInt(str[0])*60+Integer.parseInt(str[1])+Integer.parseInt(str[2])*0.01;
//			System.out.println("time="+dtime);
//		}

		/*
		 * 测试整个类
		 */
		{
			LrcData ld = new LrcData("4.lrc");				//路径\\输入文件名
			ld.printLrcDate();
		}
	}
}
 ...




分享到:
评论

相关推荐

    Java-解析歌词

    在本Java小项目中,我们聚焦于歌词解析,这是一个典型的文本处理任务,涉及到文件操作、I/O流处理以及集合框架的运用。以下是对这些技术的详细说明: 首先,文件操作是程序与本地文件系统交互的基础。在Java中,...

    java同步歌词功能

    Java同步歌词功能是一种在音乐播放器中常见的特性,它允许用户在欣赏音乐的同时,看到与当前播放时间对应的歌词。这项功能的实现主要依赖于Java编程语言以及对LRC(Lyric Repeat Character)格式的文本文件处理。LRC...

    基于java的lrc歌词文件解析工具

    本项目是基于Java实现的LRC歌词文件解析工具,它专门用于处理LRC格式的歌词文件,这种文件常用于音乐播放器以同步显示歌曲的歌词。 LRC歌词文件是一种简单的文本格式,包含了一系列的时间戳和对应的歌词内容。每个...

    java实现歌词同步显示

    3. **歌词解析**: - 解析LRC文件的关键在于识别时间戳并提取对应的歌词内容。这通常需要使用正则表达式来匹配时间戳的模式,如`\[\d{2}:\d{2}\.\d{2}\]`,并将匹配到的时间戳和歌词保存到数据结构中,如HashMap或...

    Java音乐播放器歌词同步

    - 解析LRC:你需要编写代码来解析LRC文件,将时间码与歌词一一对应,这通常涉及字符串处理和正则表达式知识。 - 时间同步:通过计算当前播放位置与歌词时间码的差值,可以实现歌词的滚动显示。 4. **多线程**: ...

    java有关音乐播放器的歌词的代码

    3. **LRC格式歌词解析**: LRC是常见的歌词文件格式,它以时间戳为索引,记录了歌词的每一句何时出现。解析LRC文件需要对字符串处理和正则表达式有深入理解。我们可以编写一个LRC解析器,将歌词按照时间顺序存储在...

    Java模仿Kugou,实现歌词秀

    总的来说,实现“Java模仿酷狗歌词秀”是一个涉及文件解析、时间同步、UI设计和用户交互的综合性项目。它不仅考验编程技能,还锻炼了对用户体验的关注。通过这样的实践,开发者可以提升自己的Java编程能力,同时对...

    java解析lrc

    Java解析LRC歌词文件是一项常见的任务,特别是在开发音乐播放软件时。LRC(Lyric Regression Caption)是一种专门用于存储歌词的格式,它以文本文件的形式存在,每行通常包含一个时间戳和对应的歌词内容。本篇文章将...

    Lrc歌词解析器

    《Lrc歌词解析器》是基于Java实现的一个程序,用于解析Lrc格式的歌词文件,以便在播放音乐时同步显示歌词。Lrc是一种常见的歌词文件格式,它将歌词按照时间戳进行分段,使得在播放特定时间点时能准确显示对应的歌词...

    基于Java语言的多种歌词格式解析器设计源码

    该项目是一款基于Java语言的歌词解析器源码,共计包含59个文件,其中包含27个Java源文件、8个KRC配置文件、7个JAR包文件、5个HRC(Happy Lyrics)歌词配置文件、2个XML和Prefs配置文件以及少量其他类型文件。...

    基于Java的JavaLRC歌词文件解析工具设计源码

    本项目是基于Java的JavaLRC歌词文件解析工具设计源码,包含42个文件,其中

    酷狗KRC格式歌词转换为LRC(附java)

    1. **读取KRC文件**:使用Java的I/O流读取KRC文件,解析其内部结构,提取歌词内容和对应的时间戳。 2. **处理时间戳**:KRC格式的时间戳可能与LRC格式不完全相同,需要进行转换或者适配。 3. **构建LRC文件**:...

    解析酷狗歌词文件

    酷狗歌词文件其实也是文本文件,为什么我们用记事本打不开呢?是因为它做了压缩处理,还把字节打乱了 哈哈 让...知道了怎么解析krc,就可以开发专属于我们自己的播放器,还支持酷狗歌词文件,是不是很有意思呢。。。

    zzlg 多媒体音乐播放器 java通过调用jmf 实现的音乐播放 歌词同步歌曲搜索 截屏等功能

    这种功能通常依赖于LRC格式的歌词文件,播放器会解析这些文件,然后根据歌曲的时间戳将歌词适时显示出来,提升用户的音乐欣赏体验。实现这一功能需要对LRC文件格式有深入理解,以及精确的时序控制技术。 歌曲搜索...

    Java Swing制作多行滚动歌词显示控件.doc

    Java Swing 制作多行滚动歌词显示控件 以下是 Java Swing 制作多行滚动歌词显示控件的详细知识点: 1. 领域模型:歌词文件的抽象 在 Java 中,我们可以使用一个类来抽象歌词文件。这个类可以命名为 ...

    音乐上传播放解析歌词

    在IT行业中,音乐上传播放与歌词解析是常见的功能,尤其在音乐播放应用或者在线音乐平台中。本项目涉及的关键技术点主要围绕JavaWeb开发,涵盖了用户交互、文件处理和文本解析等多个方面。以下是对这些知识点的详细...

    J2ME 实现mp3 歌词滚动效果源码

    在移动设备上实现多媒体功能是Java ME(J2ME)平台的一个重要应用领域,特别是对于音乐播放,歌词滚动效果能够极大地提升用户体验。本项目提供的源码着重展示了如何在J2ME环境中实现MP3歌曲的歌词同步滚动显示。下面...

    android/java外挂字幕文件解析srt

    视频外挂字幕文件解析,解析视频字幕文件,支持解析多行字幕文件,srt格式。对视频播放器外挂字幕解析可以做为一个参考。

    JMF版Java音乐播放器

    ### 文件名称解析: 1. **软件安装和操作说明.doc**:这是一份文档,详细介绍了软件的安装步骤和如何操作音乐播放器,对于用户来说非常重要,可以帮助他们顺利使用该程序。 2. **示例音乐.lrc**:LRC文件是一种歌词...

    用Java技术实现字幕滚动程序设计

    通过上述分析可以看出,这段代码展示了如何使用 Java Applet 技术来实现一个简单的字幕滚动效果。虽然 Java Applet 目前已不再广泛使用,但对于理解 Java 的历史以及图形界面编程的基础概念仍然具有一定的参考价值。...

Global site tag (gtag.js) - Google Analytics