Java-строки имеют формат UTF-16.Все остальные кодировки могут быть представлены с использованием байтовых последовательностей.Чтобы декодировать символьные данные, вы должны предоставить кодировку при первом создании строки.Если у вас есть поврежденная строка, это уже слишком поздно.
Предполагая ID3, спецификации определяют правила для кодирования.Например, ID3v2.4.0 может ограничивать кодировки, используемые через расширенный заголовок:
q - Ограничения кодировки текста
0 No restrictions
1 Strings are only encoded with ISO-8859-1 [ISO-8859-1] or
UTF-8 [UTF-8].
Обработка кодировкиопределяется далее в документе:
Если больше ничего не сказано, строки, включая числовые строки и URL-адреса, представляются в виде символов ISO-8859-1 в диапазоне от $ 20 до $ FF.Такие строки представлены в описаниях фреймов как <text string>
или <full text string>
, если разрешены переводы строки.Если ничего не сказано, символ новой строки запрещен.В ISO-8859-1 новая строка представлена, когда это разрешено, только с $ 0 А.
Кадры, которые допускают различные типы кодирования текста, содержат байт описания кодировки текста.Возможные кодировки:
$00 ISO-8859-1 [ISO-8859-1]. Terminated with $00.
$01 UTF-16 [UTF-16] encoded Unicode [UNICODE] with BOM. All
strings in the same frame SHALL have the same byteorder.
Terminated with $00 00.
$02 UTF-16BE [UTF-16] encoded Unicode [UNICODE] without BOM.
Terminated with $00 00.
$03 UTF-8 [UTF-8] encoded Unicode [UNICODE]. Terminated with
$00.
Используйте классы транскодирования, такие как InputStreamReader
или (более вероятно, в этом случае) конструктор String(byte[],Charset)
для декодирования данных.См. Также Java: приблизительное руководство по кодированию символов .
При анализе компонентов строки в структуре данных ID3v2.4.0 будет выглядеть примерно так:
//untested code
public String parseID3String(DataInputStream in) throws IOException {
String[] encodings = { "ISO-8859-1", "UTF-16", "UTF-16BE", "UTF-8" };
String encoding = encodings[in.read()];
byte[] terminator =
encoding.startsWith("UTF-16") ? new byte[2] : new byte[1];
byte[] buf = terminator.clone();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
do {
in.readFully(buf);
buffer.write(buf);
} while (!Arrays.equals(terminator, buf));
return new String(buffer.toByteArray(), encoding);
}