问题是想读取一个编码为unicode的properties文件,转换为GBK或GB2312的文件保存。
现做了如下测试,如果直接读取unicode的字符串“\u6d4b\u8bd5”,可以转换成汉字“测试”,但如果是从properties文件中读取的“\u6d4b\u8bd5”,却不能转换,请问有经验的朋友,是什么原因啊,如何解决,实现想要的功能。先谢谢了。代码1:
String str2 = "\u6d4b\u8bd5"; // \u6d4b\u8bd5 ="测试"
Charset cs = Charset.forName("GBK");     
CharsetDecoder cd = cs.newDecoder();   
CharBuffer cb = null;
try {
cb = cd.decode(ByteBuffer.wrap(str2.getBytes()));
 System.out.println(cb);
} catch (CharacterCodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();

代码2:
String fileName = "D:\\test\\a.properties";
InputStream in = null;
BufferedOutputStream bos = null;
Charset cs = Charset.forName("GBK");
CharsetDecoder cd = cs.newDecoder();
CharBuffer cb = null;
try{
in = new FileInputStream(fileName);
byte[] buffer = new byte[100];
byte[] outBytes = new byte[100];
while (in.read(buffer) > 0) {
String str = new String(buffer);
System.out.println(str);
cb = cd.decode(ByteBuffer.wrap(buffer));
System.out.println(cb);
}
} catch (IOException ex) {
ex.printStackTrace();
}
代码2中 a.properties中保存“\u6d4b\u8bd5”。
cb 和str 中打印出的都是“\u6d4b\u8bd5”,感觉cb中应该打印出“测试”,不知问题出在哪里。

解决方案 »

  1.   

    呵呵,编码转换问题没搞清楚啊!看下面:
    代码1:
    String str2 = "\u6d4b\u8bd5"; // \u6d4b\u8bd5 ="测试"
    // 在这里,编译期已经把这些字串转成“测试”的unicode编码
    // (字符串在JVM的内存里都是用unicode存储的),
    // 你会发现str2.length()已经是2了。
    Charset cs = Charset.forName("GBK");     
    CharsetDecoder cd = cs.newDecoder();   
    CharBuffer cb = null;
    try {
    cb = cd.decode(ByteBuffer.wrap(str2.getBytes()));
    // 在这里,str2.getBytes()是按操作系统的默认编码get出str2的byte[],
    // 而cd.decode()当然是按GBK编码来看待那些byte[]啦,
    // 既然你在下面能print出正确的“测试”两字,相信你的系统是GBK的吧。
     System.out.println(cb);
    } catch (CharacterCodingException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();

    代码2:
    String fileName = "D:\\test\\a.properties";
    InputStream in = null;
    BufferedOutputStream bos = null;
    Charset cs = Charset.forName("GBK");
    CharsetDecoder cd = cs.newDecoder();
    CharBuffer cb = null;
    try{
    in = new FileInputStream(fileName);
    byte[] buffer = new byte[100];
    byte[] outBytes = new byte[100];
    while (in.read(buffer) > 0) {
    // 这里是按系统默认编码来解码文件中的byte[],读取字符串,
    // 当然读出的是"\u6d4b\u8bd5"的GBK编码啦,也就是ascii的编码,
    // 所以这里in.read(buffer)的返回值应是12。
    String str = new String(buffer);
    // 这里按照GBK编码来解码buffer里的byte[],
    // 出来的其实还会是那12个字符,
    // 但因为你没有指定buffer里面有几个byte是有效的,所以后面还会出来一堆垃圾。
    System.out.println(str);
    cb = cd.decode(ByteBuffer.wrap(buffer));
    // 你这里decode其实跟上面new String()是一样的效果。
    System.out.println(cb);
    }
    } catch (IOException ex) {
    ex.printStackTrace();
    }
      

  2.   

    如果你想知道怎么得到正确的结果,看一下Properties$LineReader.loadConvert()这个方法吧。我直接给你贴出来好了:
        
        /*
         * Converts encoded \uxxxx to unicode chars
         * and changes special saved chars to their original forms
         */
        private String loadConvert (char[] in, int off, int len, char[] convtBuf) {
            if (convtBuf.length < len) {
                int newLen = len * 2;
                if (newLen < 0) {
            newLen = Integer.MAX_VALUE;
        } 
        convtBuf = new char[newLen];
            }
            char aChar;
            char[] out = convtBuf; 
            int outLen = 0;
            int end = off + len;        while (off < end) {
                aChar = in[off++];
                if (aChar == '\\') {
                    aChar = in[off++];   
                    if(aChar == 'u') {  //关键在这里!
                        // Read the xxxx
                        int value=0;
        for (int i=0; i<4; i++) {
            aChar = in[off++];  
            switch (aChar) {
              case '0': case '1': case '2': case '3': case '4':
              case '5': case '6': case '7': case '8': case '9':
                 value = (value << 4) + aChar - '0';
         break;
      case 'a': case 'b': case 'c':
                              case 'd': case 'e': case 'f':
         value = (value << 4) + 10 + aChar - 'a';
         break;
      case 'A': case 'B': case 'C':
                              case 'D': case 'E': case 'F':
         value = (value << 4) + 10 + aChar - 'A';
         break;
      default:
                                  throw new IllegalArgumentException(
                                               "Malformed \\uxxxx encoding.");
                            }
                         }
                        out[outLen++] = (char)value;
                    } else {
                        if (aChar == 't') aChar = '\t'; 
                        else if (aChar == 'r') aChar = '\r';
                        else if (aChar == 'n') aChar = '\n';
                        else if (aChar == 'f') aChar = '\f'; 
                        out[outLen++] = aChar;
                    }
                } else {
            out[outLen++] = (char)aChar;
                }
            }
            return new String (out, 0, outLen);
        }
      

  3.   

    谢谢eric1028() ,该问题已解决。