如何将128到255的字节映射到等效的UTF16-LE代理对

时间:2011-12-16 12:29:51

标签: java unicode utf-16 surrogate-pairs

我正在努力实现这个目标:

我在java web服务中有一个PDF byte [],我必须将其作为base64字符串发送到.NET客户端,以完成此任务以重建文件。

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

我无法更改客户端代码,现在java Web服务正在调用另一个.NET Web服务,它将byte []转换为base64字符串:

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

除了我可以用各种方式制作的base64(例如使用org.apache.commons.codec.binary.Base64),我必须将原始byte []转换为UTF-16LE字节[] ... < / p>

我试过了:

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 =&gt; 7F00)但对于高于(128 - > 255)的值,我不这样做知道如何获得等效的2bytes值;我知道对于字节156(9C),对应的值是8301(0x5301),对于字节224(E0),对应的值是12501(0x7D01),但我没有设法找到获取所有其他值的算法。 / p>

字节值和相应的UTF-16LE代理对之间是否存在映射表,或者是将值从128映射到255的算法?

提前致谢!

3 个答案:

答案 0 :(得分:2)

您不需要代理对;它们是处理Basic Multilingual Plane(BMP)之外的字符的构造,所有windows-1252字符都是BMP。

官方windows-1252(别名cp1252)到Unicode映射表是 http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT 它是一个易于处理的纯文本文件,因此如果您没有找到现有的转换工具,那么根据该文件编写映射应该相当简单。

该文件在官方IANA注册管理机构中间接引用: http://www.iana.org/assignments/character-sets

答案 1 :(得分:2)

byte[] encoded = new String(b, "windows-1252").getBytes("UTF-16LE");

答案 2 :(得分:0)

我终于找到了解决方案。看起来只有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);
    }

}