最近須要使用Java Swing作個讀寫Flac格式音頻文件的小GUI工具,雖然Mp3tag徹底能夠完成Flac的讀寫(編輯)任務,可是爲了簡化工做流程(編輯Flac信息後調用其它系統的接口完成部分信息上傳等功能),須要開發一個集成相似Mp3tag功能和額外功能於一體的小工具。html
開發前的思考~~,「用JDK提供的IO(NIO)讀寫Flac?...」,「Flac的格式?...」,「一直潛心於JavaWeb和服務端接口開發...幾乎沒作過Java的GUI(Swing/AWT)!...」。。java
後來,在網上Google了一下是否有第三方專門處理音頻文件(包括MP三、ape等等)的Java類庫可使用:結果用中文關鍵字檢索很難找到滿意的答案,最後在Stack Overflow搜索到一個標題爲「Reading metadata from FLAC files with Java」的Answer中找到了答案「Try using JAudiotagger. It supports MP3, MP4, Ogg Vorbis, FLAC and WMA, and it has limited support for WAV and Real.」,接着,下載jar包,或者使用Maven構建工程的話,添加dependency便可。api
<dependency> <groupId>org</groupId> <artifactId>jaudiotagger</artifactId> <version>2.0.3</version> </dependency>
其實,在讀寫Flac文件以前,仍是要先了解Flac是什麼...Free Lossless Audio Codec-自由無損音頻壓縮編碼...(貌似目前愈來愈流行無損音樂,不管是硬件播放器仍是音頻的高保真文件格式,或者原本就流行,奈我從未發現~~)app
而後就是查看JAudiotagger API,編寫代碼,就簡單多了...maven
此文不對Flac中的每個Tag信息進行英-中文對照說明,若是在音樂技術方面有深刻研究的朋友能夠私下交流溝通或有更好的網站方便提供一下,不勝感激~~PS:能夠根據Tag映射中的英文key與Mp3tag中文版對照,或許能夠找到答案。。。工具
下面說明一下讀取和寫入(編輯)Tag信息的通常步驟及可能出現的困惑或卡殼(Stuck):測試
1,閱JAudiotagger API知,使用FlacFileReader對象的read方法讀取一個Flac文件,返回一個AudioFile(接口)類型的對象(實現了該接口的類的實例),再經過AudioFile中的方法getAudioHeader和getTag分別得到AudioHeader(接口)類型的對象和FlacTag類(實現了Tag接口)的對象。網站
2, 利用得到的AudioHeader和FlacTag的對象便可得到想要的元數據(Metadata)信息,包括採樣率(SampleRate)、製做格式或製做技術(Format)、單曲名(TITLE)、單曲藝術家(ARTIST)、專輯名(ALBUM)、專輯藝術家(ALBUM_ARTIST)、音軌號(TRACK)、語言(LANGUAGE)、版權方(COPYRIGHT)等等,使用FlacTag對象的getFirstArtwork方法能夠得到圖片。編碼
3,關於FlacTag中的Tag信息的Key值,有三種狀況,一個是枚舉FieldKey中的Key,另外一個是FieldKey中沒有的可是Tag映射表中有的Key;在讀取Key對應的value值時,有兩個重載的方法:getFirst(FieldKey id)
和getFirst(java.lang.String id),後面的方法包含了Tag映射中全部的key,固然也包括FieldKey枚舉中的Key;最後一個就是Tag映射表中沒有的,也就是自定義的key。
獲取單曲名稱時,兩個方法均可以,以下:
tag.getFirst("TITLE")
tag.getFirst(FieldKey.TITLE)
可是獲取版權方Copyright(flac中對應的key是COPYRIGHT,能夠從Tag映射表中查到),可是FieldKey的枚舉中沒有(這個能夠經過修改JAudiotagger源代碼在枚舉裏面加上須要的key,不過徹底不必,JAudiotagger也只是把主要的可能比較重要比較經常使用的、通常Flac文件中都有的key放到枚舉裏面,經過重載的方法只要傳入key的字符串id參數便可),像Copyright只好使用tag.getFirst("COPYRIGHT")方法讀取版權信息。
4,在修改Tag信息時,也是有兩個方法, 和 ,緣由同3,像Copyright這樣的Tag信息只好使用tag.setField("COPYRIGHT", "XX唱片公司");了。setField(FieldKey genericKey, java.lang.String value)setField(java.lang.String vorbisCommentKey, java.lang.String value)
修改單曲名時,兩個方法均可以,以下:
tag.setField(FieldKey.TITLE, "讓一切隨風");
tag.setField("TITLE", "讓一切隨風");
仔細一點會從API發現FlacTag對象有以下方法(判讀一個Tag的key是否存在):
tag.hasField("COPYRIGHT")
若是返回true,則讀取時可能有版權信息,由於有可能只是在Flac文件中加了COPYRIGHT卻沒有設置值,沒有值則返回"",不返回null;若是返回false,顯然Flac文件中尚未COPYRIGHT;不管hasField方法返回的是true仍是false,只要被判斷的key在Tag映射表存在,均可以直接調用tag.setField("COPYRIGHT", "XX唱片公司");方法爲COPYRIGHT或者其它key設置值。
5,3和4中討論的Tag(FlacTag)信息中的key都是Tag映射中有的Key,若是想要自定義一個key,併爲自定義的key設置值,且在下次讀取該Flac文件時能夠讀出這個自定義key的值,就須要另外的方法addField(java.lang.String vorbisCommentKey, java.lang.String value)
,例如自定義一個假設叫作ISTEST的key,以下:
tag.addField("ISTEST", "true");
6, 再仔細一點就會發現,還有一個addField的重載方法,addField(FieldKey genericKey, java.lang.String value)
,這是什麼意思呢?若是執行
tag.addField("COPYRIGHT")又會怎樣呢?蠻奇怪的,爲何讀取Tag信息的時候是getFirst方法?爲何有個First呢?
假設Flac文件中已經有TITLE和COPYRIGHT,而後再執行下面兩條語句:
tag.addField(FieldKey.TITLE,"讓一切隨心");
tag.addField("COPYRIGHT","YY唱片公司");
經過調用tag.getVorbisCommentTag()方法,觀察一下OGG Tag content的內容以下:
若是分別調用getFirst方法去獲取TITLE和COPYRIGHT的值,顯然分別是「讓一切隨風」和「XX唱片公司」。
7,4中所言能夠爲Tag映射表中存在的key,即便Flac文件中沒有,也能夠經過setField方法設置值,那麼自定義的key可不能夠呢?答案是確定的,便可以使用setField爲Flac文件添加一個自定義的Tag信息。
經過API和代碼測試,addField和setField的區別固然也很容易就會想到,addField會不斷的create,而setField只在第一次設置值時發現key不存在纔會create並設置值,不然只是改變value的值。
8, 刪除Tag信息,直接刪除key便可,方法deleteField(FieldKey fieldKey)
和deleteField(java.lang.String id)
,這兩個方法均會刪除6中所add的全部相同key的Tag信息,表現就是刪除後調用hasField方法返回false。
9, API中還有createField以及對圖片的獲取、圖片信息的添加修改如setField(Artwork artwork)
等,暫不敘述。
10, 關於Tag信息修改後的保存到flac文件中去:在Tag信息經過setField方法修改後,使用FlacFileWriter對象的write方法將讀出來的AudioFile對象「寫回去」便可(flac文件只會改變set的key-value或者添加一個新的key或者刪除相同的某個key及對應value,其它的信息不會丟失)。