開篇先交代一下背景, 因爲本人喜歡在網上下載一些無損音樂放到本地聽,時間一長,導致本地存放音樂的文件夾裏的文件很多,看上去很雜亂,而一首一首歌去手動創建目錄又很複雜,所以今天休息的時候閒來無事,想到是不是可以做一個小工具,根據音樂文件的歌手和專輯名去自動創建目錄,把文件移動到創建好的目錄。
說做就做,第一步,確定需求。這裏其實很簡單,就是我輸入一個目錄,這個工具就會把該目錄下的音樂文件自動移動到對應的目錄,目錄規則爲 根目錄/歌手/專輯。確定了需求,接下來就是步驟:
- 遍歷根目錄下的所有文件;
- 篩選其中的音樂文件(有時下載的資源包括封面圖);
- 找出音樂文件的歌手和專輯名,並拼裝好新的目錄;
- 將當前音樂移動到指定目錄
下面放一下代碼,因爲本人用的是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#吧,能達到目的就好,語言只是一種手段,不需要太多的糾結。當然這個工具也僅僅是實現了簡單功能,能把大部分音樂進行比較好的分類,有些多歌手的,做的還不是很好,所以後期還會繼續改進,有其他更好想法的朋友可以提出想法,我也會適當參考的~