Кодировка текста в теги ID3v2.3 теги

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

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

пример: Данные из фрейма TIT2 начинаются с байта $ 03 (hex) перед фактическим текстом. Этот текст отображается правильно, хотя и с дополнительным символом в начале, используя кодировку.ФОРМАТ ASCII.И getString

в другом MP3 данные из TIT2 начинаются с $ 01 и сопровождаются $FF $FE, что, я считаю, связано с Unicode? Сам текст разбивается, хотя между каждым текстовым символом есть $00, и это останавливает отображение данных в windows forms (как как только встречается 00, текст просто останавливается, поэтому я получаю первый символ, и все). Я пробовал использовать кодировку.ЮНИКОД.GetString, но это, похоже, возвращает тарабарщину.

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

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

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

с уважением Росс!--1-->

3 ответов


данные из фрейма TIT2 начинаются с байта $ 03 (hex) перед фактическим текстом. Этот текст отображается правильно, хотя и с дополнительным символом в начале, используя кодировку.ФОРМАТ 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 должен ли возвращать правильную строку из этого-post некоторый код?

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

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

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


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

00-ISO-8859-1 (ASCII).

01-UCS-2 (UTF-16 закодированный Unicode с BOM), в ID3v2.2 и ID3v2.3.

02-UTF-16BE закодированный Unicode без BOM, в ID3v2.4.

03-UTF-8 закодированный Unicode, в ID3v2.4.

от: http://en.wikipedia.org/wiki/ID3


отлично, я получил код для правильного чтения Unicode & 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);
            }
        }
    }
}