Кодировка текста в тегах ID3v2.3 - PullRequest
6 голосов
/ 25 марта 2012

Благодаря этому сайту и нескольким другим я создал простой код для чтения тегов ID3v2.3 из файлов MP3. Это был большой опыт обучения, так как раньше у меня не было знаний о шестнадцатеричном / байтовом / двоичном и т. Д.

Я могу успешно читать данные, но столкнулся с проблемой, которая, как мне кажется, связана с используемой кодировкой. Я понял, что у текстовых фреймов есть байт в начале «текста», который описывает используемую кодировку, и, возможно, больше информации в следующих 2 байтах ...

Пример: Данные из кадра TIT2 начинаются с байта $ 03 (шестнадцатеричный) перед фактическим текстом. Этот текст отображается правильно, хотя с дополнительным символом в начале, с использованием Encoding.ASCII.GetString

В другом MP3 данные с TIT2 начинаются с $ 01, а за ними следует $ FF $ FE, что, на мой взгляд, связано с Unicode? Сам текст разбит, хотя между каждым текстовым символом есть $ 00, и это мешает отображению данных в формах Windows (как только встречается 00, текст просто останавливается, поэтому я получаю первый символ и все ). Я пытался использовать Encoding.UNICODE.GetString, но это, кажется, просто возвращает бред.

Кажется, что печать этих данных на консоль работает с пробелами между каждым символом, поэтому чтение данных работает правильно.

Я читал официальную документацию для ID3v2.3, но, похоже, я недостаточно разбирался, чтобы понять раздел кодирования текста.

Буду очень признателен за любые ответы или ссылки на статьи, которые могут оказаться полезными!

С уважением Росс

Ответы [ 3 ]

7 голосов
/ 14 ноября 2012

Просто добавьте еще один комментарий для кода кодировки текста:

00 - ISO-8859-1 (ASCII).

01 - UCS-2 (Unicode в кодировке UTF-16 с BOM), в ID3v2.2 и ID3v2.3.

02 - кодировка UTF-16BE в кодировке Unicode без спецификации, в ID3v2.4.

03 - Юникод в кодировке UTF-8, в ID3v2.4.

из: http://en.wikipedia.org/wiki/ID3

4 голосов
/ 25 марта 2012

Данные из кадра TIT2 начинаются с байта $ 03 (шестнадцатеричный) перед фактическим текстом. Этот текст отображается правильно, хотя с дополнительным символом в начале, с использованием Encoding.ASCII.GetString

Кодировка 0x03 - UTF-8, поэтому вы должны использовать Encoding.UTF8.GetString. Символ в начале может быть U + FEFF Byte Order Mark, который используется для различения 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 должен вернуть правильную строку из этого - опубликовать какой-нибудь код?

Печать этих данных на консоль работает

Получение символов, не относящихся к ASCII, для печати на консоли Windows может быть пробным, поэтому при возникновении проблем помните, что они могут быть вызваны самой операцией печати. ​​

Для полноты кодирование 0x02 - это UTF-16BE без спецификации (нет особых причин для этого, и я вообще никогда не встречал этого в дикой природе), а кодирование 0x00 должно быть ISO-8859-1, но в действительности это может быть любая ASCII-надмножественная кодировка, скорее кодовая страница Windows 'ANSI', такая как Encoding.GetEncoding(1252), чем стандарт, такой как 8859-1.

1 голос
/ 25 марта 2012

Отлично, я получил код для правильного чтения Юникода и ASCII (ниже)!

Хотя один вопрос - я ожидал, что Encoding.UNICODE.GetString() будет обрабатывать спецификацию, но, похоже, это не так.Насколько я понимаю, вы должны прочитать эти байты и соответственно обработать данные?Я только что удалил 2 байта, если это UNICODE ниже.

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);
            }
        }
    }
}
...