我将某些字符存在文本文档(.txt),unicode格式,用的是.getBytes("UTF-8");结果输出的是EFBFBD,按照道理应该是EF BB BF 啊
所以我想问,怎么回事?
还有就是存为.txt,utf-8格式,读出来的不符合unicode编码,也就是码位跟unicode上规定的不一样
怎么回事?

解决方案 »

  1.   

    java里 unicode == utf16 == UnicodeBig (Charset)
      

  2.   

    我知道unicode=utf-16,都是两个字节,utf-8是一个字节,但是你们都阐述了这个意思,没有解决我的问题啊
      

  3.   

    Java平台的字符编码是UTF-16 BE,但是这不代表你用java读写文件用的编码就是UTF-16。读写文件如果你不指定字符集,那么就使用默认的字符集,这个默认的字符集和你的操作系统有关。(可以由:System.getProperty("file.encoding") 获得)。
    windows 的unicode采用的是UTF-16(貌似还是little endian,也就是UTF-16 LE)。 假如你在windows下用文本工具save as unicode,那么是保存为UTF-16格式。BOM不是EF BB BF 而是FFFE(UTF-16LE),UTF-16BE是FEFF。再来看你的代码:你应该是类似于这样的方式读取的文件内容:    public static void main(String[] args) {
            String path = "test.txt";
            BufferedReader reader = null;
            
            try {
             try {
                reader = new BufferedReader(new FileReader(new File(path)));             String line;
                
                while (null != (line = reader.readLine())) {
                 byte[] bytes = line.getBytes("UTF-8");
                
                 for(byte b : bytes) {
                 System.out.println(Integer.toHexString(b & 0xFF));
                 }
                }
             }finally {
             if(bis != null) {
             bis.close();
             }
             }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }没有指定读取文件的字符集,默认用System.getProperty("file.encoding")这个字符集。这很有可能不是UTF-16,比如我设置的是UTF-8(你读出来是EFBFBD,那么你的有可能是GBK)。所以在你读取文件内容的时候就没有读出正确的内容。然后用.getBytes("UTF-8");就不可能得到正确的UTF-8的BOM。
    程序要改:    public static void main(String[] args) {
            String path = "out.txt";
            BufferedReader bis = null;
            
            try {
             try {
                bis = new BufferedReader(new InputStreamReader(new FileInputStream(new File(path)), "UTF-16LE" ));// 在这里指定字符集,根据你的操作系统指定,如果是windows,应该就是"UTF-16LE"             String line;
                
                while (null != (line = bis.readLine())) {
                 // 这里你用UTF-8在返回的byte数组的开头就是UTF-8的BOM
                 byte[] bytes = line.getBytes("UTF-8");
                
                 for(byte b : bytes) {
                 System.out.println(Integer.toHexString(b & 0xFF));
                 }
                }
             }finally {
             if(bis != null) {
             bis.close();
             }
             }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
      

  4.   

    没看明白你写的意思,我用的是scanner的方法读入的
    但是我觉得这没啥影响吧
    我试着去理解你的意思,我用的是file读入,然后filereader读入
    你后来改成了fileinputstream,是不是这个意思,字节流和字符流的区别??
    我觉得没有区别吧。
    另外问下(b & 0xFF)和ff与操作有什么用??,和全1做与操作,没啥用途啊
      

  5.   

    用Scanner还是Reader,原理都是一样的。
    重点不是字节流和字符流的区别,用fileInputStream的时候我指定了编码方式:"UTF-16LE",这是重点。
    关于 b & 0xFF:
    b是一个byte,占8位。计算机中是用补码表示二进制的,比如FE,是111111110,这在byte中是个负数(-2),因为最高位符号位是1.
    然后调用的是Integer.toHexString(int i) 这个方法,注意,参数是int类型。
    现在b是byte,要转成int类型,那么就要做类型提升。我想这个大家都比较清楚,计算机组成原理,计算机导论等..学校讲的很多了,就是高位补符号位。
    将8为二进制数1111 1110转成32位的int类型,就是高位用补符号位补足32位,结果是 1111 1111 1111 1111 1111 1111 1111 1110
    算算这个负数的原码:负数的原码 = 补码-1 然后取反码。
         1111 1111 1111 1111 1111 1111 1111 1110
     -)  0000 0000 0000 0000 0000 0000 0000 0001
      ---------------------------------------------
         1111 1111 1111 1111 1111 1111 1111 1101
    反)  1000 0000 0000 0000 0000 0000 0000 0010  (-2)现在看看这个32位数的16进制表示,
      1111 1111 1111 1111 1111 1111 1111 1110
       F    F     F    F    F    F    F    E
    看到了吧,本来是FE,现在变成了FFFFFFFE
    所以用Integer.toHexString()求一个byte的16进制表示先把这个整形的高24位清零。
    注意:直接写0xFF,这在java中是一个int类型的数,也就是说他是一个正整数。
    看看 b & 0xFF 是什么结果(由于0xFF是int,所以会先把b提升类型,然后再做计算)
        1111 1111 1111 1111 1111 1111 1111 1110(byte类型的0xFE提升到int类型的表示)
    &) 0000 0000 0000 0000 0000 0000 1111 1111 (int 类型的0xFF)
    -------------------------------------------
        0000 0000 0000 0000 0000 0000 1111 1110 
    结果会把高位的0丢掉,没意义。所以最后结果是FE。
    明白为什么要 b & 0xFF 了吧。最后:关键是我开始那段文字,代码只是做个演示,你还是不明白的话,可以把你的代码贴上来,一起看看。
      

  6.   

    谢谢你的指教,B&0xFF,我明白了
    我现在遇到的问题是基于GB2312编码的需要保存为默认的ANSI的文本文档才能读出
    基于Unicode的必须保存为Unicode的文本文档才能读出
    能不能有一种统一的方法,对任何编码类型保存为统一的类型的文本文档都能读出
    如果不能做到文本文档是统一类型的
    那么能否在读入的时候都能传String是都是一致类型的
      

  7.   

    谢谢你的指教,B&0xFF,我明白了
    我现在遇到的问题是基于GB2312编码的需要保存为默认的ANSI的文本文档才能读出
    基于Unicode的必须保存为Unicode的文本文档才能读出
    能不能有一种统一的方法,对任何编码类型保存为统一的类型的文本文档都能读出
    如果不能做到文本文档是统一类型的
    那么能否在读入的时候都能传String是都是一致类型的