如何从ipad(iphone)的酷我音乐盒中导出已下载的音乐文件

如何从ios酷我音乐盒中导出已下载的音乐文件

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

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

参考网址:

http://blog.sina.com.cn/s/blog_4d5428240101enzu.html

在网上找到了一个软件,也就是上面参考网址中的软件,但是使用的时候出现了问题,提示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、最后把源文件重命名为“歌手名 - 歌曲名.扩展名”,并移动到目标文件夹即可。

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

  1. import java.io.File;
  2. import java.sql.Connection;
  3. import java.sql.DriverManager;
  4. import java.sql.ResultSet;
  5. import java.sql.Statement;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8. public class Test {
  9. /**
  10. * 存储播放列表的数据结构
  11. *
  12. * @author jzj
  13. */
  14. static class PlayList {
  15. int id;
  16. String name;
  17. public PlayList(String name, int id) {
  18. this.name = name;
  19. this.id = id;
  20. }
  21. }
  22. // 数据库完整路径
  23. static final String db_path = "G:\\IOS\\cloud.db";
  24. // 源文件夹
  25. static final String src_dir = "G:\\IOS\\Music\\";
  26. // 目标文件夹
  27. static final String dst_dir = "G:\\IOS\\Music1\\";
  28. public static void main(String[] args) throws Exception {
  29. Class.forName("org.sqlite.JDBC");
  30. Connection conn = DriverManager.getConnection("jdbc:sqlite:" + db_path);
  31. Statement stat1 = conn.createStatement();
  32. Statement stat2 = conn.createStatement();
  33. // 读取播放列表
  34. List<PlayList> lists = new ArrayList<Test.PlayList>();
  35. ResultSet rs_list = stat1.executeQuery("select * from playlistsInfo;");
  36. while (rs_list.next()) {
  37. final int id = rs_list.getInt("id");
  38. final String name = rs_list.getString("title");
  39. switch (name) {
  40. // 忽略这几个列表
  41. case "本地歌曲":
  42. case "默认列表":
  43. case "最近播放":
  44. case "我的电台":
  45. break;
  46. case "我喜欢听":
  47. default:
  48. lists.add(new PlayList(name, id));
  49. }
  50. }
  51. // 读取音乐信息
  52. ResultSet rs_res = stat1.executeQuery("select * from musicResource;");
  53. while (rs_res.next()) {
  54. // 源文件路径
  55. String fname = rs_res.getString("file");
  56. if (fname == null || fname.length() == 0) // 如果file字段为空则跳过
  57. continue;
  58. String src_path = src_dir + fname;
  59. File src = new File(src_path);
  60. if (!src.exists()) // 如果源文件不存在则跳过
  61. continue;
  62. // 获取音乐rid
  63. int rid = rs_res.getInt("rid");
  64. // 查找该音乐所在播放列表id, 如果没有找到则为-1
  65. ResultSet rs_pl = stat2.executeQuery(new StringBuilder(
  66. "select playlist_id from playlistMusics where rid=")
  67. .append(rid).append(‘;‘).toString());
  68. int playlist_id = -1;
  69. while (rs_pl.next()) { // 默认将一首歌放在编号最大的播放列表中(也就是最新创建的列表)
  70. int p_id = rs_pl.getInt("playlist_id");
  71. if (p_id > playlist_id)
  72. playlist_id = p_id;
  73. }
  74. rs_pl.close();
  75. // 目标文件夹路径
  76. StringBuilder b2 = new StringBuilder(dst_dir);
  77. if (playlist_id >= 0) {
  78. String playlist_name = getPlaylist(lists, playlist_id);
  79. if (playlist_name != null) {
  80. b2.append(playlist_name).append(‘\\‘);
  81. }
  82. }
  83. String dir = b2.toString();
  84. new File(dir).mkdirs();
  85. // 目标文件名: "艺术家 - 歌曲名.扩展名"
  86. StringBuilder b3 = new StringBuilder();
  87. b3.append(rs_res.getString("artist")).append(" - ")
  88. .append(rs_res.getString("title")).append(‘.‘)
  89. .append(rs_res.getString("format"));
  90. String dst_path = dir + b3.toString();
  91. // 移动和重命名
  92. File dst = new File(dst_path);
  93. src.renameTo(dst);
  94. // 输出信息
  95. System.out.println(new StringBuilder(src_path).append(" ---> ")
  96. .append(dst_path));
  97. }
  98. rs_res.close();
  99. conn.close();
  100. }
  101. static String getPlaylist(List<PlayList> lists, int playlist_id) {
  102. for (PlayList pl : lists) {
  103. if (pl.id == playlist_id)
  104. return pl.name;
  105. }
  106. return null;
  107. }
  108. }

由于涉及数据库操作,需要在Java工程中添加数据库支持包,可参看这篇文章 http://ttitfly.iteye.com/blog/143934

使用nested包:sqlitejdbc-v037-nested.jar

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

完整工程可在此下载:

http://pan.baidu.com/s/1hGNT0

如何从ipad(iphone)的酷我音乐盒中导出已下载的音乐文件

时间: 2024-07-30 12:54:01

如何从ipad(iphone)的酷我音乐盒中导出已下载的音乐文件的相关文章

如何从ios酷我音乐盒中导出已下载的音乐文件(使用Java编程实现)

如何从ios酷我音乐盒中导出已下载的音乐文件 本文所涉及内容用于技术学习,请勿用于不正当用途,否则后果自负. 酷我音乐ios版下载的音乐文件,通过同步助手等软件查看时,发现音乐文件都是一串数字命名.通过网上查找和自己尝试,发现那些文件都是音频文件改了文件名而已.只要修改回文件名,就能和正常的音乐一样播放了. 参考网址: http://blog.sina.com.cn/s/blog_4d5428240101enzu.html 在网上找到了一个软件,也就是上面参考网址中的软件,但是使用的时候出现了问

Java代码实现向Oracle数据库中导入已备份的数据库文件

今天将很早就实现的一个Oracle数据库备份功能粘贴出来,这个功能是在大学做阶段设计时写的: import java.io.IOException; /** * Java代码实现向Oracle数据库中导入已备份的数据库文件 * * @author:Gaohuanjie */ public class OracleImportDatabase { /** * 向Oracle数据库中导入已备份的数据库文件 * * @author:Gaohuanjie * @param userName 进入数据库所

Xcode中关于已删除图片或文件 编译出现CpResource或者CopyPNGFile can&#39;t find file的错误

Xcode中关于已删除图片或文件 编译出现CpResource或者CopyPNGFile can't find file的错误   今天整理项目,准备把未用到的png给删了,结果 编译出现CopyPNGFile error找不到文件 和 CpResource error , No such file or directory等错误.仔细检查发现图片确实删了,代码中相关的代码也都修改掉了,但是一直编译不成功,最后google一把 Xcode也没有任何的相关解决办法. 那么只好用最粗暴的手段直接修改

命令行从Android手机中导出已安装APK的方法调研

一.背景 二.步骤 一.背景 很多时候,APK文件只存在于应用市场,在PC上无法直接下载.用手机下载下来后就直接安装了,也不能保存原始的APK文件. APK安装到手机后,Android系统会保存一份和原始APK一模一样的拷贝,位于data/app目录,文件名为“APK的包名-1.apk”或者“APK的包名-2.apk”.这里的包名即 package name,形如 com.xxx.xxx. data/app这个目录在非root的情况下,是无法直接查看的.但幸运的是,这个目录下所有的APK文件,是

在Java中导出word、excel格式文件时JSP页面头的设置

我们在JSP中往往会把一些表格里的东西需要导出到本地,一般都是导成word.excel格式的文件.这只需要在JSP页面头设置及在<head></head>标签中添加下面的代码: 导出为excel: <% response.setContentType("application/vnd.ms-excel;charset=UTF-8"); response.setHeader("Content-Disposition","atta

在ArcGIS中导出现有mxd的style文件

做好的地图包含许多地图符号,这是之前花了很多功夫做的,怎么把它导出来再用呢? 在ArcGIS中右键工具栏,customize,选择command选项卡,在搜索框中输入style ,选择tools,将第一个工具“export map styles”拖动到工具栏上,就可以用啦.

Allegro从.brd文件中导出器件封装

Allegro从.brd文件中导出器件封装打开.brd文件,File→Export→Libraries,除了No libraries dependencies之外,所有选项都勾选上,设定好存放路径之后,Export!! 注意事项:1. 一般的,将.dra, .pad, .psm, .fsm, .fsm文件存入path\symbols文件夹,而将.txt文件存入path\devices文件夹,然后再在PCB Editor中设置路径:Setup→User Preferences→Design Pat

iOS中使用ZipArchive压缩和解压缩文件-备

为什么我需要解压缩文件 有许多原因能解释为什么我要在工程中使用压缩和解压缩功能,下面是几个常见的原因: 苹果App Store的50M下载限制 苹 果公司出于流量的考虑,规定在非WIFI环境下,限制用户只能下载小于50M的应用或游戏.这样一来,对于一些数据或数据包较大的应用,我们只能尽量减小 应用二进制包的体积.而把数据打包到zip中,这样App可以通过网络下载数据包,解压出所需要的内容,而且这样也可以动态的更新内容. 动态更新内容 这 一点在上面已经提过了.如果应用所需要的资源需要动态更新,一

iOS中使用ZipArchive 压缩和解压缩文件

引自 http://www.36duo.com/thread-119-1-1.html 在本教程中,我将演示如何在iOS程序中压缩和解压缩文件.我们将使用一个叫做ZipArchive的第三方库来实现.尽管压缩和解压缩有许多其他的方案可选,但是我觉得ZipArchive库是最快捷.最简单的解决方案.let’s go. 为什么我需要解压缩文件 有许多原因能解释为什么我要在工程中使用压缩和解压缩功能,下面是几个常见的原因: 苹果App Store的50M下载限制 苹 果公司出于流量的考虑,规定在非WI