各位,InputStream is = new FileInputStream("D:\\Work_beiruan\\source\\1.txt"); int c;
while ((c = is.read()) != -1) {
System.out.print((char) c);
}
System.out.println();这段代码,在1.txt中有英文也有中文,可是读中文时打印出来是乱码,读英文就正常。请问:
字节流读写英文和汉字时有什么区别?为什么读英文没事?读中文就乱码?有人说是因为一个汉字占两个字节,可是一个英文字母不也是一个char吗?也是占两个字节啊。请高手帮忙解释一下,不胜感激。

解决方案 »

  1.   

    那个返回的int值,好像是ascii码来的,
    在读中文的时候,1个字分2次来读,所以会变成乱码
      

  2.   


    public static void main(String[] args)throws Exception {
    InputStream is = new FileInputStream("1.txt");
    Reader reader = new InputStreamReader(is);
            int c;
            while ((c = reader.read()) != -1) {
                System.out.print((char) c);
            }
            System.out.println();
    }
      

  3.   

    的确英文也是两个字节,但是unicode编码的英文编码是和ascii码相同的,简单点说,英文只用了一个字节,而那个返回的int 其实只是读取了一个byte数据,也就是说一个int只有一个字节是有用的,我也搞不懂他为什么不直接返回byte - -
    如果需要读取中文的话建议还是用字符流,用InputStreamReader 转换成Reader就行了- -
    Reader reader = new InputStreamReader(new FileInputStream(path));
    reader.read(); 
      

  4.   

    一个字母是16位,但是它只是用了低8位,这是为了和ascii码兼容,注意unicode码前127个字符和ascii码是一样的。其实字节流一次就读取了一个字节,返回byte更加正确一点,返回一个int有时会让人误解- -
      

  5.   

    谢谢您的回复。其实我不是为了读中文,我只是想不明白,在读英文字母的时候一次也是读出一个字节(8bit),即便是可以正确读出每个字母,剩下的那8bit呢?如果默认是0,那除了读出英文字母外,还应该有其它的符号才对呀,可实际上除了英文字母,并没有出现其它的东西啊!
      

  6.   

    java的char是unicode编码(基本上可以认为是utf-8) ,c的才是ascii。 java的byte和c的char比较对应。
    utf-8是不等长的,用utf-8表示"中"占用2个字节,"a"则是1个字节。
      

  7.   

    public static void main(String[] args)throws Exception {
            InputStream is = new FileInputStream("1.txt");
            Reader reader = new InputStreamReader(is, "UTF-8");//GB2312
            int c;
            while ((c = reader.read()) != -1) {
                System.out.print((char) c);
            }
            System.out.println();
        }
      

  8.   

    public static void main(String[] args)throws Exception {
      InputStream is = new FileInputStream("1.txt");
      Reader reader = new InputStreamReader(is, "UTF-8");//GB2312
      int c;
      while ((c = reader.read()) != -1) {
      System.out.print((char) c);
      }
      System.out.println();
      
      

  9.   


    InputStream is = new FileInputStream("D:\\1.txt");
            int c;
            while ((c = is.read()) != -1) {
                System.out.print((char) c);
                System.out.println("---");
            }
            System.out.println();输出为:
    t---
    e---
    s---
    t---
    ?---
    ?---
    ?---
    °---
    从输出可以看出,一次确实只读了一个字节
      

  10.   

    我其实不太明白你的问题在哪里
    这么说吧,字节流使一次读取一个字节的,而英文的unicode是只用了一个字节,所以读取没有问题,而中文是占用了两个字节,所以当你读取一个字节的时候会造成截断。
    然后java把一个byte的数据转换成int,高位用0补上,然后再截断,变成2个字节,高位那个字节还是0,至于你说的为什么没有问题,是因为你不是把它转换城 char 型输出吗,这样的话就一次读取了2个字节啦,这两个字节作为一个整体输出,既然是整体的一个char,高位的0为什么又会变成乱码呢?
    不知道有没有达到重点- -
      

  11.   

    我是这样想的啊,不知道对不对?java把文件内容封装成输入流,其实就是把文件内容封装成一个byte流,这个过程是按照操作系统存储的机制有关。可能在操作系统中,一个英文字母占8位,一个中文占16位。在这一封装过程中,出现英文可以,中文乱码的情况。
      

  12.   


    InputStream is = new FileInputStream("D:\\1.txt");        byte[] u = {'a','a'};
            while (is.read(u) != -1) {
                System.out.print(new String(u));
            }
            System.out.println();这样的代码能正确读出中文,说明不是在封装的时候出现乱码的。应该是在is.read()的时候读到了不认识的字符而产生的乱码。至于为什么不认识,我觉得字母的高8位存在某种特征,read()的时候发现了,就会认识是字母,所以能正常显示。读到中文的时候,因为只读了一半的字,java不认识这个字符,就会解成u003F,就会显示?
      

  13.   

    貌似一开始我理解错了你的问题- -
    具体的的底层实现我也不太清楚,菜鸟一只,很难回答你的问题。
    不过我想操作系统里面应该有类似字符分隔一类的特殊字符或者用了什么算法吧,反正操作系统是能够分得清哪几个字节是一个字的吧。不过我想应该是统一的字节数才对,而不是说英文一个字节,中文两个字节。说到底,中文英文什么的在都是1010的数据罢了,哪里分得清哪几个字节是英文,那几个是中文(当然,如果说有所谓的字符分隔的方式存在的话,还是可能分辨得出的)。至于你说的为什么英文没有乱码我大概懂你问什么了,如果说写进去的unicode两个字节里面高位是 0 然后读出来的 0 为什么没有乱码,我想大概是因为,00000000  在unicode里面和在ascii里面都是空字符的意思。而空字符打印出来就是什么都没有,那么既然你什么都没有看到,也就会认为没有乱码出现什么的咯,事实上也的确没有。
    可以验证一下
    试着读取一个全英文的文件,用一个计数器,每读取一次就输出一个字符,计数器自增1,然后再把输出次数跟
    你看到的字符数目比较一下,如果比例大概是2:1的话,上面的推论就是正确的了。
    也就是说改为的0有输出,但是你看不到。我用同学的电脑上网,做实验因该不太可能的了,哪位有兴趣可以试一试,期待结果。
      

  14.   

    我觉得应该是在read()前,就是根据本地字符集对文件中的内容进行了处理,一般windows下是GBK编码,那么ByteArray-GBK〉String:0x61 0xD6 0xD0 0xCE 0xC4-〉/u0061/u4E2D/u6587(a中文)
    英文会变成一个字符,而中文变成了2个字符,而read()的时候是一个字符一个字符的读,所以会产生这种情况。
      

  15.   

    貌似中文乱码那点我没说因为中文在unicode里面是一定把2个字节全占用了的,而字节流一次读取一个字节,把两个字节给隔断了,会出现有乱码什么的。
    记得以前看过说用字符流去读取中英文混搭的文本,里面提到过一种识别中文的方法。
    因为文本里面只有中英文两种字符(标点符号除外,不过标点符号是属于ascii码的范围的)
    考虑到unicode前127个字符兼容ascii,所以把标点符号和英文统一处理,读到就输出。而如果读到中文,就把下一个字节读进来,两个字节处理一下再装进一个String 或char里面输出,貌似可以把两个字节放进一个字节数组里面,然后 用String 的构造方法构造字符串输出。当然,还有很多方法。
    至于识别一个字节是一个英文还是中文的办法,我记得不太清楚了,只记得书上说一个字节有八位,而127个字符只2能占据后7位,也就是说,英文和标点由于是这127个字符之一,所以最高位一定是0,而根据中文在unicode离得位置,可以判断中文两个字节里面最高位一定是1,所以,当读取一个字节之后,判断它的大小是否大于127(最高位是不是1),是的话说明这是一个中文的第一个字节,把下一个字节读进来处理然后输出。
    如果没记错的话,大概就是这样子了
    不过现实中应该用不到这么麻烦的方法- -
      

  16.   

    shuwei003和ITkey,说的都有道理,不过我是这样认为的:在操作系统中,一个英文字母占1个字节(8位),一个汉字占2个字节,这是我从操作系统书籍上查到的。所以,用字节流一个字节一个字节读文本文件时,英文字母一下正好读过来;而每次都中文时,都需要截断读取,所以中文出现乱码。
      

  17.   

    对不起,我这个是只限于win95等某些OS,不适用于win2000,xp等系统。所以不能这样理解。
      

  18.   

    我突然觉得这个好像跟unicode没什么关系,读文件,是根据默认字符集一般windows中是GBK从文件中读取到输入流,然后使用read()从输入流中一个一个字符读取。使用GBK编码读取的时候字母占一个字符,中文占2个字符。
      

  19.   

    InputStream is = new FileInputStream("1.txt");
    Reader reader = new InputStreamReader(is, "UTF-8");
    BufferedReader r=new BufferedReader(reader);
    r.readLine();
      

  20.   

    package com.sinotrust.cn;import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStreamReader;public class readText { /**
     * @param args
     */
    public static void main(String[] args) {
    // InputStream is = null;
    // try {
    // is = new FileInputStream("E:\\1.txt");
    // } catch (FileNotFoundException e) {
    // e.printStackTrace();
    // }
    // int c;
    // try {
    // while ((c = is.read()) != -1) {
    // System.out.print((char) c);
    // }
    // } catch (IOException e) {
    // e.printStackTrace();
    // }
    // System.out.println(); try {
    String encoding = "GBK"; // 字符编码(可解决中文乱码问题 )
    File file = new File("E:\\1.txt");
    if (file.isFile() && file.exists()) {
    InputStreamReader read = new InputStreamReader(new FileInputStream(file), encoding);
    BufferedReader bufferedReader = new BufferedReader(read);
    String lineTXT = null;
    while ((lineTXT = bufferedReader.readLine()) != null) {
    // System.out.println(lineTXT );
    // 将文本读取出来的字符去掉"," 因为读取出来的字符是用","来分隔的
    String text = lineTXT.replaceAll(",", "");
    // 用字符分隔成数组
    String[] version_1 = text.split("-");
    for (int i = 0; i < version_1.length; i++) {
    String[] version_2 = version_1[i].split(":");
    for (int j = 0; j < version_2.length; j++) {
    System.out.println(version_2[j]);
    }
    System.out.println("-------");
    }
    }
    read.close();
    } else {
    System.out.println("找不到指定的文件!");
    }
    } catch (Exception e) {
    System.out.println("读取文件内容操作出错");
    e.printStackTrace();
    }
    }
    }
      

  21.   

    package com.sinotrust.cn;import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStreamReader;public class readText { /**
     * @param args
     */
    public static void main(String[] args) {
    // InputStream is = null;
    // try {
    // is = new FileInputStream("E:\\1.txt");
    // } catch (FileNotFoundException e) {
    // e.printStackTrace();
    // }
    // int c;
    // try {
    // while ((c = is.read()) != -1) {
    // System.out.print((char) c);
    // }
    // } catch (IOException e) {
    // e.printStackTrace();
    // }
    // System.out.println(); try {
    String encoding = "GBK"; // 字符编码(可解决中文乱码问题 )
    File file = new File("E:\\1.txt");
    if (file.isFile() && file.exists()) {
    InputStreamReader read = new InputStreamReader(new FileInputStream(file), encoding);
    BufferedReader bufferedReader = new BufferedReader(read);
    String lineTXT = null;
    while ((lineTXT = bufferedReader.readLine()) != null) {
    // System.out.println(lineTXT );
    // 将文本读取出来的字符去掉"," 因为读取出来的字符是用","来分隔的
    String text = lineTXT.replaceAll(",", "");
    // 用字符分隔成数组
    String[] version_1 = text.split("-");
    for (int i = 0; i < version_1.length; i++) {
    String[] version_2 = version_1[i].split(":");
    for (int j = 0; j < version_2.length; j++) {
    System.out.println(version_2[j]);
    }
    System.out.println("-------");
    }
    }
    read.close();
    } else {
    System.out.println("找不到指定的文件!");
    }
    } catch (Exception e) {
    System.out.println("读取文件内容操作出错");
    e.printStackTrace();
    }
    }
    }
      

  22.   

    问题出在
      while ((c = is.read()) != -1) {
                System.out.print((char) c);
            }
    想想看,英文都是一个byte,而中文为二个byte,这样一个byte读取中文不出现乱码才奇怪呢!
    比较好的方法参考:
     contentByte = new byte[BYTELENGTH];
            while ((byteReturnSize = bis.read(contentByte, 0, contentByte.length)) >= 0) {
                byteBuffer.append(contentByte, 0, byteReturnSize);
            }
            xmlBody = new String(byteBuffer.toByteArray());楼上readline也会有问题