При доступе к системным ресурсам Windows (связанным со звуком) я обнаружил, что Windows предоставляет строки описания указанных ресурсов, используя свою собственную кодировку, в то время как Java обрабатывает эти строки так же, как и все строки по умолчанию: в кодировке unicode. Так что вместо толкового текста получил кучу вопросительных знаков:
????????? ???????? ???????
Используя метод String .codePointAt(), я обнаружил, что эти вопросы на самом деле скрывают некоторый текст с кодировкой Windows-1252. Что, конечно же, хотелось бы увидеть. Так начался мой крестовый поход по преобразованию этой строки во что-то читабельное.
Полдня спустя, после того, как я порылся в Stackoverflow и Google по связанным темам, я получил некоторый прогресс, но это привело только к большему количеству вопросов. Итак, мой код:
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import javax.sound.sampled.AudioSystem;
public class Study_Encoding {
//private static final Charset utf8Charset = Charset .forName ("UTF-8");
private static final Charset win1251Charset = Charset .forName ("Windows-1251");
private static final Charset win1252Charset = Charset .forName ("Windows-1252");
public static void main(String[] args) {
String str = AudioSystem .getMixerInfo () [0] .getName ();
System .out .println ("Original string:");
System .out .println (str + "\n");
System .out .println ("Its code-points:");
displayCodePointSequence (str);
System .out .println ("Windows-1251-decoded byte array (wrong):");
byte [] win1251ByteArr = str .getBytes (win1251Charset);
displayByteSequence (win1251ByteArr);
System .out .println ("Windows-1252-decoded byte array (right):");
byte [] win1252ByteArr = str .getBytes (win1252Charset);
displayByteSequence (win1252ByteArr);
System .out .println ("Windows-1252-encoded string (wrong):");
try {
System .out .println (win1252Charset .newDecoder ()
.decode (ByteBuffer .wrap (win1252ByteArr)) .toString () + "\n");
} catch (Exception e) {
System .out .println ("ERROR:" + e .toString ());
}
System .out .println ("Windows-1251-encoded string (right):");
try {
System .out .println (win1251Charset .newDecoder ()
.decode (ByteBuffer .wrap (win1252ByteArr)) .toString () + "\n");
} catch (Exception e) {
System .out .println ("ERROR:" + e .toString ());
}
}
private static void displayCodePointSequence (String str) {
if (null == str) {
System .out .println ("No string");
return;
}
if (str .isEmpty ()) {
System .out .println ("Empty string");
return;
}
for (int k = 0; str .length () > k; ++k) {
System .out .print (str .codePointAt (k) + " ");
}
System .out .println ("[" + str .length () + "]\n");
}
private static void displayByteSequence (byte [] byteArr) {
if (null == byteArr) {
System .out .println ("No array");
return;
}
if (0 == byteArr .length) {
System .out .println ("Empty array");
return;
}
for (int k = 0; byteArr .length > k; ++k) {
System .out .print ((((int) byteArr [k]) & 0xFF) + " ");
}
System .out .println ("[" + byteArr .length + "]\n");
}
}
Эта программа выводит следующий вывод (где последняя строка — это то, что я хочу получить):
Original string:
????????? ???????? ???????
Its code-points:
207 229 240 226 232 247 237 251 233 32 231 226 243 234 238 226 238 233 32 228 240 224 233 226 229 240 [26]
Windows-1251-decoded byte array (wrong):
63 63 63 63 63 63 63 63 63 32 63 63 63 63 63 63 63 63 32 63 63 63 63 63 63 63 [26]
Windows-1252-decoded byte array (right):
207 229 240 226 232 247 237 251 233 32 231 226 243 234 238 226 238 233 32 228 240 224 233 226 229 240 [26]
Windows-1252-encoded string (wrong):
????????? ???????? ???????
Windows-1251-encoded string (right):
Первичный звуковой драйвер
Как видно, кодировки win1251 и win1252 почему-то перепутались. Кроме того, я думаю, есть способ заставить Java-программу обрабатывать все строки как строки в какой-то собственной кодировке (чего я НЕ ХОЧУ!!!) или, по крайней мере, предоставляемой системой как единое целое. Так,...
... мои вопросы:
- Как преобразовать строку? (Что я решил, я думаю)
- Что происходит? (со смешанными кодировками и всем остальным)
- Как это сделать правильно? (Получение строки, если нет, преобразование строки)
РЕДАКТИРОВАТЬ:
Кажется, я не ясно выразился, но я говорю не о содержимом текстовых файлов, а о системных строках, таких как имена и описания устройств (физических и виртуальных), может быть, имена файлов и каталогов. В приведенном выше примере строка «Первичный звуковой драйвер» должна быть чем-то вроде «Аудиоустройство по умолчанию» в английской версии Windows.