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

Java 如何将128到255的字节映射到等效的UTF16-LE代理项对,java,unicode,utf-16,surrogate-pairs,Java,Unicode,Utf 16,Surrogate Pairs,我正在努力做到这一点: 我在java web服务中有一个PDF字节[],我必须将它作为base64字符串发送到.NET客户端,该客户端执行此操作以重建文件 Encoding.Convert(Encoding.Unicode, Encoding.Default, Convert.FromBase64String(inputJava)) 我无法更改客户端代码,现在java web服务正在调用另一个.NET web服务,该服务将字节[]转换为base64字符串: System.Text.Encodi

我正在努力做到这一点:

我在java web服务中有一个PDF字节[],我必须将它作为base64字符串发送到.NET客户端,该客户端执行此操作以重建文件

Encoding.Convert(Encoding.Unicode, Encoding.Default, Convert.FromBase64String(inputJava))
我无法更改客户端代码,现在java web服务正在调用另一个.NET web服务,该服务将字节[]转换为base64字符串:

System.Text.Encoding.Convert(System.Text.Encoding.GetEncoding(1252), System.Text.Encoding.Unicode, b);
除了可以通过各种方式(例如使用org.apache.commons.codec.binary.base64)生成的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; 
}
byte[]输出=新字节[b.length*2];
for(int i=0;i
这适用于128以下的值(例如,对于1=>0100,2=>0200,…,127=>7F00),但对于高于(128->255)的值,我不知道如何获得等效的2字节值;我知道字节156(9C)对应的值是8301(0x5301),字节224(E0)对应的值是12501(0x7D01),但我没有找到一个算法来获取所有其他值

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


提前谢谢

您不需要代理项对;它们是用于处理基本多语言平面(BMP)之外的字符的结构,所有windows-1252字符都使用BMP

官方的windows-1252(别名cp1252)到Unicode映射表为 它是一个易于处理格式的纯文本文件,因此如果您没有找到用于转换的现有工具,那么基于该文件编写映射应该相当简单

该文件在IANA官方注册处间接引用:
我终于找到了解决办法。看起来只有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);
    }

}
公共类编码器{
静态映射mapTiny=newHashMap(){
公共整数get(对象键){
整数代码=super.get(key);
如果(代码==null)
代码=(整数)键;
返回码;
}
};
静止的{
mapTiny.put(1288364);
mapTiny.put(1308218);
mapTiny.put(131402);
mapTiny.put(1328222);
mapTiny.put(1338230);
mapTiny.put(1348224);
mapTiny.put(1358225);
mapTiny.put(136710);
mapTiny.put(1378240);
mapTiny.put(138352);
mapTiny.put(1398249);
mapTiny.put(140338);
mapTiny.put(142381);
mapTiny.put(1458216);
mapTiny.put(1468217);
mapTiny.put(1478220);
mapTiny.put(1488221);
mapTiny.put(1498226);
mapTiny.put(1508211);
mapTiny.put(1518212);
mapTiny.put(152732);
mapTiny.put(1538482);
mapTiny.put(154353);
mapTiny.put(1558250);
mapTiny.put(156339);
mapTiny.put(158382);
mapTiny.put(159376);
}
公共静态字符串编码(字节[]b)引发IOException{
ByteArrayInputStream in=新的ByteArrayInputStream(b);
ByteArrayOutputStream convFileByteArray=新建ByteArrayOutputStream();
int i=in.read();
而(i!=-1){
convFileByteArray.write(新字节[]{(字节)(mapTiny.get(i)和0xff),(字节)(mapTiny.get(i)>>8)和0xff)});
i=in.read();
}
返回Base64.encodeToString(convFileByteArray.toByteArray(),false);
}
}

我不完全清楚您想要什么,但肯定包含您需要的所有内容。+1:我会使用
ISO-8859-1
而不是
windows-1252
,甚至只使用
新字符串(b,0)只是为了确保没有翻译。@PeterLawrey-为什么是ISO-8859-1?OP显示数据是使用windows 1252字符集编码的。虽然,我想如果数据真的是base64编码的,那么这两种方式都不重要。也可以使用US-ASCII。@jtahlborn:我试过用它,也试过用不同的字符集组合,但不幸的是,我没能使它正常工作:用java编码的base64字符串与在.NET中生成的不同,并检查字节[]在编码之前,我看到128以上字节的代理项对是不同的。我怀疑微软的Encoding.Unicode与java的UTF-16LE有多大的不同。另外,正如之前有人建议我的,第一个字符集(Cp1252)应该无关紧要,因为该文件是二进制文件,而不是编码文本文件…@Nicola-字符之间有什么区别?具体来说,您要检查哪个字节[]?也许如果您显示更多代码…@jtahlborn:例如:原始字节[]中的字节0x90变为.NET:0x9000,而在java中变为0xFDFF(使用windows-1252作为编码)。如果我改为使用iso-8859-1,则特定字符是正确的,但其他字符编码不好。谢谢你,NicolaThanks,使用你提供的链接中的列表,我成功地理解了这个问题。仅供参考,这基本上是windows-1252编码,我相信我上面的示例也应该完成同样的事情。是的,这是我尝试的第一件事,但令人惊讶的是它没有起作用。也许这是我虚拟机中的一个错误。。。
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);
    }

}