Unicode ID3v2.3标记中的文本编码

Unicode ID3v2.3标记中的文本编码,unicode,encoding,hex,ascii,id3,Unicode,Encoding,Hex,Ascii,Id3,多亏了这个网站和其他一些网站,我创建了一些简单的代码来读取MP3文件中的ID3v2.3标签。这样做是一次很好的学习经历,因为我以前不知道十六进制/字节/二进制等 我可以成功地读取数据,但遇到了一个问题,我认为这与所使用的编码有关。我已经意识到文本帧在“文本”的开头有一个字节,描述所使用的编码,在接下来的2个字节中可能会有更多的信息 例如: 第2帧的数据以实际文本前的字节$03(十六进制)开始。此文本使用Encoding.ASCII.GetString正确显示,尽管在开头有一个附加字符 在另一个M

多亏了这个网站和其他一些网站,我创建了一些简单的代码来读取MP3文件中的ID3v2.3标签。这样做是一次很好的学习经历,因为我以前不知道十六进制/字节/二进制等

我可以成功地读取数据,但遇到了一个问题,我认为这与所使用的编码有关。我已经意识到文本帧在“文本”的开头有一个字节,描述所使用的编码,在接下来的2个字节中可能会有更多的信息

例如: 第2帧的数据以实际文本前的字节$03(十六进制)开始。此文本使用Encoding.ASCII.GetString正确显示,尽管在开头有一个附加字符

在另一个MP3中,TIT2中的数据以$01开头,后面跟着$FF$FE,我认为这与Unicode有关?文本本身被分解,每个文本字符之间有$00,这会阻止数据在windows窗体中显示(一旦遇到00,文本就会停止,所以我得到第一个字符,就是这样)。我尝试过使用Encoding.UNICODE.GetString,但这似乎是胡言乱语

将这些数据打印到控制台似乎是可行的,每个字符之间都有空格,因此数据的读取工作正常

我一直在阅读ID3v2.3的官方文档,但我想我还没有完全理解文本编码部分

任何回复或文章链接,可能会有帮助,将不胜感激

问候 罗斯

第2帧的数据以实际文本前的字节$03(十六进制)开始。此文本使用Encoding.ASCII.GetString正确显示,尽管在开头有一个附加字符

编码0x03是UTF-8,因此应该使用
Encoding.UTF8.GetString
。开头的字符可以是U+FEFF字节顺序标记,用于区分UTF-16LE和UTF-16BE。。。UTF-8没有用,但Windows工具还是喜欢把它放在那里

UTF-8是ID3v2.4的一个特性,2.3中没有,这可能就是为什么在规范中找不到它的原因。在现实世界中,无论版本如何,ID3标签中都会出现各种各样的废话

TIT2中的数据以$01开头,后面跟着$FF$FE,我认为这与Unicode有关?文本本身被分解,每个文本字符之间有$00

这就是UTF-16LE,Windows错误地称之为“Unicode”的文本到字节编码。它由两个字节码单元组成,因此U+0000–U+00FF范围内的字符显示为相同数字的低字节,后跟零高字节。0xFF-0xFE前缀是正确使用的字节顺序标记
Encoding.Unicode.GetString
应该从此帖子返回正确的字符串一些代码

将这些数据打印到控制台似乎有效

在Windows控制台上打印非ASCII字符可能是一种尝试,因此,如果遇到问题,请记住它们可能是由打印操作本身引起的


为了完整起见,编码0x02是没有BOM的UTF-16BE(这几乎没有理由存在,我在野外从未见过),编码0x00应该是ISO-8859-1,但实际上几乎可以是任何ASCII超集编码,更可能是Windows“ANSI”代码页,如
encoding.GetEncoding(1252)
比像8859-1这样的标准好。

太好了,我已经得到了一些正确读取Unicode和ASCII的代码(如下)

不过有一个问题-我希望
Encoding.UNICODE.GetString()
能够处理BOM表,但似乎没有。我认为您必须读取这些字节,并自己相应地处理数据?如果下面是UNICODE,我刚刚去掉了2个字节

public class Frame
{
    FrameHeader _header;
    public string data;
    public string name;


    public Frame(FrameHeader frm, byte[] bytes)
    {
        _header = frm;
        name = _header._name;
        if (!name.Equals("APIC"))
        {
            byte[] actualdata;
            int y;
            int x;
            int encoding = bytes[0];

            if (encoding.Equals(1))
            {
                y = 3;
                actualdata = new byte[bytes.Length - 3];
                for (x = 0; x < (bytes.Length - 3); x++, y++)
                    actualdata[x] = bytes[y];
                data = Encoding.Unicode.GetString(actualdata);
            }
            else
            {
                y = 1;
                actualdata = new byte[bytes.Length - 1];
                for (x = 0; x < (bytes.Length - 1); x++, y++)
                    actualdata[x] = bytes[y];
                data = Encoding.ASCII.GetString(actualdata);
            }
        }
    }
}
公共类框架
{
帧头_头;
公共字符串数据;
公共字符串名称;
公共帧(帧头frm,字节[]字节)
{
_标题=frm;
名称=_头。_名称;
如果(!name.Equals(“APIC”))
{
字节[]实际数据;
int-y;
int x;
整数编码=字节[0];
if(编码等于(1))
{
y=3;
actualdata=新字节[bytes.Length-3];
对于(x=0;x<(bytes.Length-3);x++,y++)
实际数据[x]=字节[y];
数据=Encoding.Unicode.GetString(实际数据);
}
其他的
{
y=1;
actualdata=新字节[bytes.Length-1];
对于(x=0;x<(bytes.Length-1);x++,y++)
实际数据[x]=字节[y];
数据=Encoding.ASCII.GetString(actualdata);
}
}
}
}

只需为文本编码代码再添加一条注释:

00–ISO-8859-1(ASCII)

01–在ID3v2.2和ID3v2.3中的UCS-2(UTF-16编码的带BOM的Unicode)

02–在ID3v2.4中,UTF-16应采用Unicode编码,无BOM

03–ID3v2.4中的UTF-8编码Unicode

发件人:

为了完整起见,ISO-8859-1是拉丁文-1(0..127中的ASCII+128..255中的西欧重音字符),尽管它不是规范,我见过没有BOM的ID3v2.3 UTF标记(01)。它被编码为UTF-16BE。我不确定是否存在某种非官方的默认设置,但Windows和第三方工具似乎能够正确地对其进行解码。