我在Android项目中使用beaglebuddy Java库来读取/写入mp3文件的ID3标签。我在阅读以前使用相同库编写的文本时遇到问题,但在文档中找不到任何相关内容。
假设我写下以下信息:
MP3 mp3 = new MP3(pathToFile);
mp3.setLeadPerformer("Jon Skeet");
mp3.setTitle("A Million Rep");
mp3.save();
查看库的源代码,我看到UTF-16编码是显式设置的,在内部调用
protected ID3v23Frame setV23Text(String text, FrameType frameType) {
return this.setV23Text(Encoding.UTF_16, text, frameType);
}
和
protected ID3v23Frame setV23Text(Encoding encoding, String text, FrameType frameType) {
ID3v23FrameBodyTextInformation frameBody = null;
ID3v23Frame frame = this.getV23Frame(frameType);
if(frame == null) {
frame = this.addV23Frame(frameType);
}
frameBody = (ID3v23FrameBodyTextInformation)frame.getBody();
frameBody.setEncoding(encoding);
frameBody.setText(encoding == Encoding.UTF_16?Utility.getUTF16String(text):text);
return frame;
}
稍后,我读了数据,它给了我一些奇怪的汉字:
mp3.getLeadPerformer(); // 䄀 䴀椀氀氀椀漀渀 刀攀瀀
mp3.getTitle(); // 䨀漀渀 匀欀攀攀琀
我看了一下内置的Utility.getUTF16String(String)
方法:
public static String getUTF16String(String string) {
String text = string;
byte[] bytes = string.getBytes(Encoding.UTF_16.getCharacterSet());
if(bytes.length < 2 || bytes[0] != -2 || bytes[1] != -1) {
byte[] bytez = new byte[bytes.length + 2];
bytes[0] = -2;
bytes[1] = -1;
System.arraycopy(bytes, 0, bytez, 2, bytes.length);
text = new String(bytez, Encoding.UTF_16.getCharacterSet());
}
return text;
}
我不太明白将前2个字节分别设置为-2和-1,这是一个模式,表明该字符串是UTF-16编码的吗?
但是,我尝试在读取数据时显式调用此方法,这似乎是可读的,但始终在一开始就预设了一些神秘的字符:
Utility.getUTF16String(mp3.getLeadPerformer()); // ��Jon Skeet
Utility.getUTF16String(mp3.getTitle()); // ��A Million Rep
由于这些字符的数量似乎是不变的,我只是通过简单地删除它们来创建一个临时的解决方法。
像“评论”这样的字段,其中作者在写入时没有明确强制执行UTF-16而没有任何问题。
我真的很好奇这里发生了什么,并感谢任何建议。