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