Как сопоставить байты от 128 до 255 эквивалентным суррогатным парам UTF16-LE - PullRequest
2 голосов
/ 16 декабря 2011

Я пытаюсь добиться этого:

У меня есть PDF-байт [] в веб-сервисе java, который я должен отправить в виде строки base64 клиенту .NET, который делает это для восстановления файла.

Encoding.Convert(Encoding.Unicode, Encoding.Default, Convert.FromBase64String(inputJava))

Я не могу изменить код клиента, и сейчас веб-сервис java вызывает другой веб-сервис .NET, который делает это, чтобы превратить байт [] в строку base64:

System.Text.Encoding.Convert(System.Text.Encoding.GetEncoding(1252), System.Text.Encoding.Unicode, b);

Помимо base64, который я могу сделать различными способами (например, с помощью org.apache.commons.codec.binary.Base64), я должен превратить исходный байт [] в байт UTF-16LE [] ...

Я пробовал это:

byte[] output = new byte[b.length * 2];
for(int i=0; i < b.length; i++) 
{
  int val = b[i];
  if(val < 0) val += 256;

  output[2*i + 0] = (byte) (val);   
  output[2*i + 1] = 0; 
}

Это прекрасно работает для значений ниже 128 (например, для 1 => 0100, 2 => 0200, ..., 127 => 7F00), но для значений выше(128 -> 255) Я не знаю, как получить эквивалентные 2-байтовые значения;Я знаю, что для байта 156 (9C) соответствующее значение равно 8301 (0x5301), а для байта 224 (E0) соответствующее значение равно 12501 (0x7D01), но мне не удалось найти алгоритм для получения всех других значений.

Существует ли таблица отображения между байтовым значением и соответствующей суррогатной парой UTF-16LE или алгоритм для отображения значений от 128 до 255?

Заранее спасибо!

Ответы [ 3 ]

2 голосов
/ 16 декабря 2011
byte[] encoded = new String(b, "windows-1252").getBytes("UTF-16LE");
2 голосов
/ 16 декабря 2011

Вам не нужны суррогатные пары; они предназначены для работы с символами вне Базовой многоязычной плоскости (BMP), и все символы windows-1252 находятся в BMP.

Официальной таблицей сопоставления Unicode для windows-1252 (псевдоним cp1252) является http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT Это простой текстовый файл в простом для обработки формате, поэтому, если вы не нашли существующий инструмент для преобразования, было бы довольно просто написать сопоставление на основе этого файла.

Файл косвенно цитируется в официальном реестре IANA: http://www.iana.org/assignments/character-sets

0 голосов
/ 22 декабря 2011

Я наконец нашел решение.Похоже, что суррогатным парам нужны только байты от 128 до 159.Я использую этот кусок кода для эмуляции кодировки .NET Unicode:

public class Encoder {
   static Map<Integer, Integer> mapTiny = new HashMap<Integer, Integer>() {
        public Integer get(Object key) {
            Integer code = super.get(key);
            if (code == null)
                code = (Integer) key;
            return code;
        }
    };

    static {
        mapTiny.put(128,8364);
        mapTiny.put(130,8218);
        mapTiny.put(131,402);
        mapTiny.put(132,8222);
        mapTiny.put(133,8230);
        mapTiny.put(134,8224);
        mapTiny.put(135,8225);
        mapTiny.put(136,710);
        mapTiny.put(137,8240);
        mapTiny.put(138,352);
        mapTiny.put(139,8249);
        mapTiny.put(140,338);
        mapTiny.put(142,381);
        mapTiny.put(145,8216);
        mapTiny.put(146,8217);
        mapTiny.put(147,8220);
        mapTiny.put(148,8221);
        mapTiny.put(149,8226);
        mapTiny.put(150,8211);
        mapTiny.put(151,8212);
        mapTiny.put(152,732);
        mapTiny.put(153,8482);
        mapTiny.put(154,353);
        mapTiny.put(155,8250);
        mapTiny.put(156,339);
        mapTiny.put(158,382);
        mapTiny.put(159,376);
    }


public static String encode(byte[] b) throws IOException {

        ByteArrayInputStream in = new ByteArrayInputStream(b);
        ByteArrayOutputStream convFileByteArray = new ByteArrayOutputStream();
        int i = in.read();
        while (i != -1) {
            convFileByteArray.write(new byte[] { (byte) (mapTiny.get(i) & 0xff), (byte) ((mapTiny.get(i) >> 8) & 0xff) });
            i = in.read();
        }
        return Base64.encodeToString(convFileByteArray.toByteArray(), false);
    }

}
...