音乐文件自动整理工具

开篇先交代一下背景, 因为本人喜欢在网上下载一些无损音乐放到本地听,时间一长,导致本地存放音乐的文件夹里的文件很多,看上去很杂乱,而一首一首歌去手动创建目录又很复杂,所以今天休息的时候闲来无事,想到是不是可以做一个小工具,根据音乐文件的歌手和专辑名去自动创建目录,把文件移动到创建好的目录。

 

说做就做,第一步,确定需求。这里其实很简单,就是我输入一个目录,这个工具就会把该目录下的音乐文件自动移动到对应的目录,目录规则为 根目录/歌手/专辑。确定了需求,接下来就是步骤:

  1. 遍历根目录下的所有文件;
  2. 筛选其中的音乐文件(有时下载的资源包括封面图);
  3. 找出音乐文件的歌手和专辑名,并拼装好新的目录;
  4. 将当前音乐移动到指定目录

下面放一下代码,因为本人用的是Windows系统,为了省事,这次就用了C#开发(主要是WinForm用着顺手),如果大家有更好的实现方式或者更棒的算法,欢迎提出~

目录结构(其实挺简单的,Logic层完全可以省略的)

界面(也很简单,不会做美工啥的,自己用的,实现功能为主吧)

按钮部分代码(这里没什么主要逻辑,还是调用MainLogic为主):

        private void btnStart_Click(object sender, EventArgs e)
        {
            string rootPath = this.tbRootPath.Text.Trim();
            MainLogic mainLogic = new MainLogic();
            if (mainLogic.isPathExist(rootPath))
            {
                try
                {
                    List<string> listFile = new List<string>();
                    DirectoryInfo directory = new DirectoryInfo(rootPath);
                    mainLogic.findFile(listFile, directory);
                    int num = 0;
                    foreach(string fileName in listFile)
                    {
                        if (mainLogic.isMusicFile(fileName))
                        {
                            string targetPath = rootPath;
                            string artist = mainLogic.getArtist(fileName);
                            string album = mainLogic.getAlbum(fileName);
                            if (!string.IsNullOrEmpty(artist) && !mainLogic.isAllQuestionMark(artist))
                            {
                                targetPath += "\\" + artist;
                            }
                            if (!string.IsNullOrEmpty(album) && !mainLogic.isAllQuestionMark(album))
                            {
                                targetPath += "\\" + album;
                            }
                            mainLogic.moveFile(fileName, targetPath);
                            num++;
                        }
                    }
                    showSuccessMessage("移动完成,本次处理文件" + num + "个");
                }
                catch (Exception ex)
                {
                    showErrorMessage(ex.Message);
                }
            }
            else
            {
                showErrorMessage("输入的路径不存在,请确认后操作");
            }
        }

遍历目录(这里还是使用递归,只记录文件,没有记录目录,代码部分引用自网友,感谢网友的无私分享~)

        public void findFile(List<string> listFiles, DirectoryInfo directoryInfo)
        {
            FileInfo[] fileInfos = directoryInfo.GetFiles();
            for (int i=0; i< fileInfos.Length; i++)
            {
                listFiles.Add(fileInfos[i].FullName);
            }
            DirectoryInfo[] directoryInfos = directoryInfo.GetDirectories();
            for (int i=0; i < directoryInfos.Length; i++)
            {
                findFile(listFiles, directoryInfos[i]);
            }
        }

判断格式,因为有时会下载出封面等其他信息,我自己最后是只保留的音乐文件,所以这里没有管,如果大家有需求可以根据需要更改代码~

        /// <summary>
        /// 判断文件是否为音乐文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public bool isMusicFile(string fileName)
        {
            string extension = Path.GetExtension(fileName);
            string targetExtension = ".mp3;.flac;.wma;.wav";
            if (targetExtension.IndexOf(extension) != -1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

获取歌手和专辑信息(文件的其他信息也可以使用这个方法获取,可自行研究)

        /// <summary>
        /// 获取歌手名
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string getArtist(string fileName)
        {
            try
            {
                Shell32.Shell shell = new Shell();
                Folder dir = shell.NameSpace(System.IO.Path.GetDirectoryName(fileName));
                FolderItem item = dir.ParseName(System.IO.Path.GetFileName(fileName));
                string artist = dir.GetDetailsOf(item, 20);
                return artist;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 获取专辑名
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string getAlbum(string fileName)
        {
            try
            {
                Shell32.Shell shell = new Shell();
                Folder dir = shell.NameSpace(System.IO.Path.GetDirectoryName(fileName));
                FolderItem item = dir.ParseName(System.IO.Path.GetFileName(fileName));
                string album = dir.GetDetailsOf(item, 14);
                return album;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

移动文件:

        /// <summary>
        /// 移动文件
        /// </summary>
        /// <param name="sourcefileName"></param>
        /// <param name="targetDir"></param>
        public void moveFile(string sourcefileName, string targetDir)
        {
            try
            {
                if (!Directory.Exists(targetDir))
                {
                    Directory.CreateDirectory(targetDir);
                }
                if (!File.Exists(sourcefileName))
                {
                    throw new Exception("文件【" + sourcefileName + "】不存在,请检查");
                }
                int index = sourcefileName.LastIndexOf("\\");
                string fileName = sourcefileName.Substring(index);
                string targetDestination = targetDir + fileName;
                if (!File.Exists(targetDestination))
                {
                    File.Move(sourcefileName, targetDestination);
                    //File.Delete(sourcefileName);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

后期发现一个问题,有些文件因为资源问题,专辑名和歌手都是问号,这里如果没有发现的话,就会造成有带问号的文件夹,还得自己处理,这里的办法是对这类文件不做处理,不拼接目录名,具体代码在上面界面的部分,下面为判断是否全部为问号的代码:

        /// <summary>
        /// 校验信息是否全为问号(有些歌曲文件会出现这种问题,可交由人工判断,或完成填写后使用)
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        public bool isAllQuestionMark(string info)
        {
            bool result = true;
            for (int i=0; i<info.Length; i++)
            {
                if (info[i] != '?')
                {
                    result = false;
                    break;
                }
            }
            return result;
        }

好了,至此就是这个小工具截至目前的主要代码,详细代码可以在这里看到:https://github.com/RazrZhang/MusicFilesHandler

小工具初版下载:

链接:https://pan.baidu.com/s/1T1pTYJn2JLaHmuLr1U-R8g
提取码:rr87
运行效果大概是下面的样子

整理前
软件界面
整理完成

 

整理后

 

 

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

写在最后:这个工具完成后比我预想的要简单一些,本来以为不同格式的文件要分开处理,但是后来发觉不需要,添加一个引用直接就完事了~这个工具运用System.IO这个库比较多,自己之前用这个类库用的也不是很多, 这次就当是做了一个练习吧,也想过用Java做,毕竟自己主攻方向是Java,但是自己GUI学的不咋地,而且又不如WinForm直接拖过来用就完事了,所以暂且就用C#吧,能达到目的就好,语言只是一种手段,不需要太多的纠结。当然这个工具也仅仅是实现了简单功能,能把大部分音乐进行比较好的分类,有些多歌手的,做的还不是很好,所以后期还会继续改进,有其他更好想法的朋友可以提出想法,我也会适当参考的~

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章