zoukankan      html  css  js  c++  java
  • 如何为ios酷我音乐盒下载导出的音乐文件(使用Java程序设计)

    这个工具已经准备第二版,读者了解编程软件,可以直接使用,请阅读和使用这个场地 http://blog.csdn.net/jzj1993/article/details/44459983



    本文所涉及内容用于技术学习。请勿用于不正当用途,否则后果自负。

    酷我音乐ios版下载的音乐文件,通过同步助手等软件查看时,发现音乐文件都是一串数字命名。通过网上查找和自己尝试,发现那些文件都是音频文件改了文件名称而已。仅仅要改动回文件名称,就能和正常的音乐一样播放了。


    在网上找到了一个软件。也就是上面參考网址中的软件。可是使用的时候出现了问题,提示subscript out of range,程序不能继续运行。于是就决定自己用Java写一个来处理。


    首先从手机复制出cloud.db数据库文件。为SQLite数据库文件。用SQLite Database Browser打开,看到里面和音乐关系比較密切的主要有三个table,playlistsInfo中保存着播放列表信息,字段title为列表名称,字段id为列表id。playlistMusics保存了音乐和播放列表的相应关系,字段title、artist等为音乐信息。rid为音乐资源id,字段playlist_id相应了所属播放列表id。musicResource中是音乐信息和文件相应关系。字段file为相应的文件名称,format为文件格式。rid为音乐资源id。



    于是程序的工作流程是这种:
    1、首先从musicResource逐一读取每首音乐的rid。
    2、通过rid在playlistMusics中查找playlist_id。可能找不到,也可能不止一个,由于同一首音乐可能在多个列表中,这里简单的取最大的playlist_id,通常应该是相对照较新的播放列表。
    3、然后在playlistsInfo中找到playlist_id相应的播放列表名。作为目标音乐的子目录;
    4、最后把源文件重命名为“歌手名 - 歌曲名.扩展名”,并移动到目标目录就可以。

    为方便交流学习,这里提供本程序源代码。

    import java.io.File;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.Statement;
    import java.util.ArrayList;
    import java.util.List;
    
    public class Test {
    
    	/**
    	 * 存储播放列表的数据结构
    	 * 
    	 * @author jzj
    	 */
    	static class PlayList {
    		int id;
    		String name;
    
    		public PlayList(String name, int id) {
    			this.name = name;
    			this.id = id;
    		}
    	}
    
    	// 数据库完整路径
    	static final String db_path = "G:\IOS\cloud.db";
    	// 源目录
    	static final String src_dir = "G:\IOS\Music\";
    	// 目标目录
    	static final String dst_dir = "G:\IOS\Music1\";
    
    	public static void main(String[] args) throws Exception {
    
    		Class.forName("org.sqlite.JDBC");
    		Connection conn = DriverManager.getConnection("jdbc:sqlite:" + db_path);
    
    		Statement stat1 = conn.createStatement();
    		Statement stat2 = conn.createStatement();
    
    		// 读取播放列表
    		List<PlayList> lists = new ArrayList<Test.PlayList>();
    		ResultSet rs_list = stat1.executeQuery("select * from playlistsInfo;");
    		while (rs_list.next()) {
    			final int id = rs_list.getInt("id");
    			final String name = rs_list.getString("title");
    			switch (name) {
    			// 忽略这几个列表
    			case "本地歌曲":
    			case "默认列表":
    			case "近期播放":
    			case "我的电台":
    				break;
    			case "我喜欢听":
    			default:
    				lists.add(new PlayList(name, id));
    			}
    		}
    
    		// 读取音乐信息
    		ResultSet rs_res = stat1.executeQuery("select * from musicResource;");
    		while (rs_res.next()) {
    
    			// 源文件路径
    			String fname = rs_res.getString("file");
    			if (fname == null || fname.length() == 0) // 假设file字段为空则跳过
    				continue;
    
    			String src_path = src_dir + fname;
    
    			File src = new File(src_path);
    			if (!src.exists()) // 假设源文件不存在则跳过
    				continue;
    
    			// 获取音乐rid
    			int rid = rs_res.getInt("rid");
    
    			// 查找该音乐所在播放列表id, 假设没有找到则为-1
    			ResultSet rs_pl = stat2.executeQuery(new StringBuilder(
    					"select playlist_id from playlistMusics where rid=")
    					.append(rid).append(';').toString());
    			int playlist_id = -1;
    			while (rs_pl.next()) { // 默认将一首歌放在编号最大的播放列表中(也就是最新创建的列表)
    				int p_id = rs_pl.getInt("playlist_id");
    				if (p_id > playlist_id)
    					playlist_id = p_id;
    			}
    			rs_pl.close();
    
    			// 目标目录路径
    			StringBuilder b2 = new StringBuilder(dst_dir);
    			if (playlist_id >= 0) {
    				String playlist_name = getPlaylist(lists, playlist_id);
    				if (playlist_name != null) {
    					b2.append(playlist_name).append('\');
    				}
    			}
    			String dir = b2.toString();
    			new File(dir).mkdirs();
    
    			// 目标文件名称: "艺术家 - 歌曲名.扩展名"
    			StringBuilder b3 = new StringBuilder();
    			b3.append(rs_res.getString("artist")).append(" - ")
    					.append(rs_res.getString("title")).append('.')
    					.append(rs_res.getString("format"));
    			String dst_path = dir + b3.toString();
    
    			// 移动和重命名
    			File dst = new File(dst_path);
    			src.renameTo(dst);
    
    			// 输出信息
    			System.out.println(new StringBuilder(src_path).append(" ---> ")
    					.append(dst_path));
    		}
    		rs_res.close();
    		conn.close();
    	}
    
    	static String getPlaylist(List<PlayList> lists, int playlist_id) {
    		for (PlayList pl : lists) {
    			if (pl.id == playlist_id)
    				return pl.name;
    		}
    		return null;
    	}
    }
    


    因为涉及数据库操作,须要在Javaproject中加入数据库支持包,可參看这篇文章 http://ttitfly.iteye.com/blog/143934
    使用nested包:sqlitejdbc-v037-nested.jar

    将音频文件所有复制出来,放到程序中src_dir所指定的文件夹,数据库文件cloud.db保存在db_path指定的位置,设置好目标文件夹dst_dir。运行程序就可以整流导出的音频文件,实測700多首音乐,仅仅需不到一分钟时间就可以完毕重命名和移动工作。

    完整project可在此下载:

    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    软件工程作业--评价自己经常使用的输入法
    课堂练习-找水王
    软件工程——找水王(续)
    软件工程——评价输入法
    软件工程——《你的灯亮着吗》读书笔记
    软件工程——课堂练习“找水王”
    软件工程结队项目——智能点餐系统典型用户及用户场景分析
    软件工程课堂练习——N层电梯只停一层求乘客爬楼层数最少(基本方法+优化方法)
    软件工程课堂练习——求买书最低价格
    结队项目——智能订餐系统用户调研报告
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4619462.html
Copyright © 2011-2022 走看看