/** To change this template, choose Tools | Templates
* and open the template in the editor.*/packagecom.hadeslee.audiotag.tag.ape;importcom.hadeslee.audiotag.tag.FieldDataInvalidException;importcom.hadeslee.audiotag.tag.KeyNotFoundException;importcom.hadeslee.audiotag.tag.Tag;importcom.hadeslee.audiotag.tag.TagField;importcom.hadeslee.audiotag.tag.TagFieldKey;importjava.io.ByteArrayOutputStream;importjava.io.File;importjava.io.IOException;importjava.io.RandomAccessFile;importjava.io.UnsupportedEncodingException;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.Iterator;importjava.util.List;importjava.util.Map;importjava.util.logging.Level;importjava.util.logging.Logger;importjavax.sound.sampled.UnsupportedAudioFileException;/***
*@authorhadeslee*/publicclassAPEv2TagimplementsTag {privatestaticLogger log=Logger.getLogger(APEv2Tag.class.getName());privateFile input;privateTagHead head;privateTagBody body;privateString artist="";privateString album="";privateString title="";privateString year="";privateString comment="";privateString track="";privateString genre="";privateintfieldCount;privateMapmap;publicAPEv2Tag(File file)throwsIOException, UnsupportedAudioFileException {this.input=file;
map=newHashMap();
load();
}publicAPEv2Tag() {
map=newHashMap();
}protectedvoidload()throwsIOException, UnsupportedAudioFileException {
RandomAccessFile raf=newRandomAccessFile(input,"r");//先查看最后32个字节try{
raf.seek((int) (input.length()-32));byte[] buffer=newbyte[32];
raf.read(buffer);
head=newTagHead(buffer);if(head.isValid()) {
log.log(Level.INFO,"读取:最后32个字节有标签!");intsize=head.getTagSize();
raf.seek((int) (input.length()-size));
buffer=newbyte[size-32];intread=0;while(read
read+=raf.read(buffer, read, buffer.length-read);
}
body=newTagBody(buffer);
Listlist=body.getItems();for(TagItem item : list) {
log.log(Level.INFO, item.toString());
}
}else{//再查看128前面的32个字节raf.seek((int) (input.length()-32-128));
raf.read(buffer);
head=newTagHead(buffer);if(head.isValid()) {
log.log(Level.INFO,"读取:ID3v1前面的字节有标签!");intsize=head.getTagSize();
raf.seek((int) (input.length()-size-128));
buffer=newbyte[size-32];intread=0;while(read
read+=raf.read(buffer, read, buffer.length-read);
}
body=newTagBody(buffer);
Listlist=body.getItems();for(TagItem item : list) {
log.log(Level.INFO, item.toString());
}
}else{thrownewUnsupportedAudioFileException("读取:找不到APEv2格式的标签!");
}
}
}finally{try{
raf.close();
readTag();
}catch(Exception exe) {thrownewUnsupportedAudioFileException("读取:找不到APEv2格式的标签!");
}
}
}privatevoidreadTag() {for(TagItem item : body.getItems()) {
map.put(item.getId(), item.getContent());
}this.album=map.get(APEv2FieldKey.Album.name());this.artist=map.get(APEv2FieldKey.Artist.name());this.comment=map.get(APEv2FieldKey.Comment.name());this.genre=map.get(APEv2FieldKey.Genre.name());this.title=map.get(APEv2FieldKey.Title.name());this.track=map.get(APEv2FieldKey.Track.name());this.year=map.get(APEv2FieldKey.Year.name());
}protectedListreturnFieldToList(TagItem field) {
Listfields=newArrayList();
fields.add(field);returnfields;
}/*** 写出APE标签到文件里面去
*@paramraf 随机文件流
*@paramhasID3v1 是否有ID3v1标签
*@throwsjava.io.IOException*/publicvoidwrite(RandomAccessFile raf,booleanhasID3v1)throwsIOException {//如果有ID3标签,则先把它缓存起来,总共128个字节byte[] temp=null;intdeleteLength=0;if(hasID3v1) {
temp=newbyte[128];
raf.seek(raf.length()-128);
raf.read(temp);
deleteLength+=128;
}
TagHead header=checkTag(raf);//如果有标头,则说明有APE的标签,还要多删一些if(header!=null) {
log.log(Level.INFO,"原来存在APEv2标签,先删除之
");intlength=header.getTagSize();if(header.hasHeader()) {//如果有标头的话,长度还要加32个字节length+=32;
}
deleteLength+=length;
}else{
log.log(Level.INFO,"以前不存在APEv2标签,直接添加
");
}
raf.setLength(raf.length()-deleteLength);//把该截掉的都截了以后,就开始写标签了,先写APE的,再看//有没有ID3的,有就写,没有就不写了raf.seek(raf.length());byte[] data=getTagBytes();
raf.write(data);if(temp!=null) {
raf.write(temp);
}
log.log(Level.INFO,"APEv2标签写出完毕
");
}/*** 得到标签所代表的字节数组
*@return标签所代表的字节数组*/privatebyte[] getTagBytes()throwsUnsupportedEncodingException, IOException {intitemCount=map.size();
body=newTagBody();for(Map.Entryen : map.entrySet()) {
body.addTagItem(newTagItem(en.getKey(), en.getValue()));
}byte[] bodyData=body.getBytes();
log.log(Level.SEVERE,"BODYSIZE="+bodyData.length);
TagHead header=newTagHead();
header.setFlag(TagHead.HEAD);
header.setItemCount(itemCount);
header.setTagSize(bodyData.length+32);
header.setVersion(TagHead.V2);
TagHead foot=newTagHead();
foot.setFlag(TagHead.FOOT);
foot.setItemCount(itemCount);
foot.setTagSize(bodyData.length+32);
foot.setVersion(TagHead.V2);
ByteArrayOutputStream bout=newByteArrayOutputStream();
bout.write(header.getBytes());
bout.write(bodyData);
bout.write(foot.getBytes());
bout.flush();returnbout.toByteArray();
}/*** 检查是否已经存在APE的标签了,主要查两个地方
* 一个是最后的字节,还有一个是最后128字节以上的字节
* 因为最后的字节可能写入了ID3v1标签
*@paramraf 文件
*@return得到标签头
*@throwsjava.io.IOException*/privateTagHead checkTag(RandomAccessFile raf)throwsIOException {
raf.seek((int) (raf.length()-32));byte[] buffer=newbyte[32];
raf.read(buffer);
TagHead header=newTagHead(buffer);if(header.isValid()) {
header.setIndex(0);returnheader;
}else{
raf.seek((int) (raf.length()-32-128));
raf.read(buffer);
header=newTagHead(buffer);if(header.isValid()) {
header.setIndex(128);returnheader;
}else{returnnull;
}
}
}/*** 删除标签,如果存在ID3v1的话,就要先保存它然后删除后面部份
* 把它写回来
*@paramraf 写出文件
*@paramhasID3v1 是否有ID3v1标签
*@throwsjava.io.IOException*/publicvoiddelete(RandomAccessFile raf,booleanhasID3v1)throwsIOException {//如果有ID3标签,则先把它缓存起来,总共128个字节byte[] temp=null;intdeleteLength=0;if(hasID3v1) {
temp=newbyte[128];
raf.seek(raf.length()-128);
raf.read(temp);
deleteLength+=128;
}
TagHead header=checkTag(raf);//如果有标头,则说明有APE的标签,还要多删一些if(header!=null) {
log.log(Level.INFO,"原来存在APEv2标签,先删除之
");intlength=header.getTagSize();if(header.hasHeader()) {//如果有标头的话,长度还要加32个字节length+=32;
}
deleteLength+=length;
}
raf.setLength(raf.length()-deleteLength);
log.log(Level.INFO,"APEv2标签删除完毕
");
}publicvoidadd(TagField field)throwsFieldDataInvalidException {
}publicvoidaddAlbum(String album)throwsFieldDataInvalidException {
setAlbum(album);
}publicvoidaddArtist(String artist)throwsFieldDataInvalidException {
setArtist(artist);
}publicvoidaddComment(String comment)throwsFieldDataInvalidException {
setComment(comment);
}publicvoidaddGenre(String genre)throwsFieldDataInvalidException {
setGenre(genre);
}publicvoidaddTitle(String title)throwsFieldDataInvalidException {
setTitle(title);
}publicvoidaddTrack(String track)throwsFieldDataInvalidException {
setTrack(track);
}publicvoidaddYear(String year)throwsFieldDataInvalidException {
setYear(year);
}publicListget(String id) {returnnull;
}publicListgetAlbum() {if(getFirstAlbum().length()>0) {
TagItem field=newTagItem(APEv2FieldKey.Album.name(), getFirstAlbum());returnreturnFieldToList(field);
}else{returnnewArrayList();
}
}publicListgetArtist() {if(getFirstAlbum().length()>0) {
TagItem field=newTagItem(APEv2FieldKey.Artist.name(), getFirstArtist());returnreturnFieldToList(field);
}else{returnnewArrayList();
}
}publicListgetComment() {if(getFirstAlbum().length()>0) {
TagItem field=newTagItem(APEv2FieldKey.Comment.name(), getFirstComment());returnreturnFieldToList(field);
}else{returnnewArrayList();
}
}publicListgetGenre() {if(getFirstAlbum().length()>0) {
TagItem field=newTagItem(APEv2FieldKey.Genre.name(), getFirstGenre());returnreturnFieldToList(field);
}else{returnnewArrayList();
}
}publicListgetTitle() {if(getFirstAlbum().length()>0) {
TagItem field=newTagItem(APEv2FieldKey.Title.name(), getFirstTitle());returnreturnFieldToList(field);
}else{returnnewArrayList();
}
}publicListgetTrack() {if(getFirstAlbum().length()>0) {
TagItem field=newTagItem(APEv2FieldKey.Track.name(), getFirstTrack());returnreturnFieldToList(field);
}else{returnnewArrayList();
}
}publicListgetYear() {if(getFirstAlbum().length()>0) {
TagItem field=newTagItem(APEv2FieldKey.Year.name(), getFirstYear());returnreturnFieldToList(field);
}else{returnnewArrayList();
}
}publicString getFirstAlbum() {returnthis.album;
}publicString getFirstArtist() {returnartist;
}publicString getFirstComment() {returncomment;
}publicString getFirstGenre() {returngenre;
}publicString getFirstTitle() {returntitle;
}publicString getFirstTrack() {returntrack;
}publicString getFirstYear() {returnyear;
}publicbooleanhasCommonFields() {returntrue;
}publicbooleanhasField(String id) {thrownewUnsupportedOperationException("Not supported yet.");
}publicbooleanisEmpty() {thrownewUnsupportedOperationException("Not supported yet.");
}publicvoidset(TagField field)throwsFieldDataInvalidException {
TagFieldKey genericKey=TagFieldKey.valueOf(field.getId());switch(genericKey) {caseARTIST:
setArtist(field.toString());break;caseALBUM:
setAlbum(field.toString());break;caseTITLE:
setTitle(field.toString());break;caseGENRE:
setGenre(field.toString());break;caseYEAR:
setYear(field.toString());break;caseCOMMENT:
setComment(field.toString());break;
}
}publicvoidsetAlbum(String s)throwsFieldDataInvalidException {this.album=s;
map.put(APEv2FieldKey.Album.name(), album);
}publicvoidsetArtist(String s)throwsFieldDataInvalidException {this.artist=s;
map.put(APEv2FieldKey.Artist.name(), s);
}publicvoidsetComment(String s)throwsFieldDataInvalidException {this.comment=s;
map.put(APEv2FieldKey.Comment.name(), s);
}publicvoidsetGenre(String s)throwsFieldDataInvalidException {this.genre=s;
map.put(APEv2FieldKey.Genre.name(), s);
}publicvoidsetTitle(String s)throwsFieldDataInvalidException {this.title=s;
map.put(APEv2FieldKey.Title.name(), s);
}publicvoidsetTrack(String s)throwsFieldDataInvalidException {this.track=s;
map.put(APEv2FieldKey.Track.name(), s);
}publicvoidsetYear(String s)throwsFieldDataInvalidException {this.year=s;
map.put(APEv2FieldKey.Year.name(), s);
}publicTagField createTagField(TagFieldKey genericKey, String value)throwsKeyNotFoundException, FieldDataInvalidException {thrownewUnsupportedOperationException("Not supported yet.");
}publicString getFirst(String id) {thrownewUnsupportedOperationException("Not supported yet.");
}publicString getFirst(TagFieldKey id)throwsKeyNotFoundException {thrownewUnsupportedOperationException("Not supported yet.");
}publicTagField getFirstField(String id) {thrownewUnsupportedOperationException("Not supported yet.");
}publicvoiddeleteTagField(TagFieldKey tagFieldKey)throwsKeyNotFoundException {thrownewUnsupportedOperationException("Not supported yet.");
}publicIterator getFields() {thrownewUnsupportedOperationException("Not supported yet.");
}publicintgetFieldCount() {thrownewUnsupportedOperationException("Not supported yet.");
}publicbooleansetEncoding(String enc)throwsFieldDataInvalidException {returnfalse;
}publicListget(TagFieldKey id)throwsKeyNotFoundException {thrownewUnsupportedOperationException("Not supported yet.");
}publicstaticvoidmain(String[] args)throwsException {
System.out.println(0xD2);//APEv2Tag tag = new APEv2Tag(new File("D:\\难道爱一个人有错吗.mp3"));//tag.load();//System.out.println("tag.album:" + tag.getFirstAlbum());//System.out.println("tag.title:" + tag.getFirstTitle());//System.out.println("tag.artist:" + tag.getFirstArtist());}
}