这段代码很简单,就是从一个文本文件读字节,然后转成String打印出来,public class TestStream {
public static void main(String[] args) throws Exception{
//q.txt带有中文和中文特有的标点符号。保存为ANSI编码格式
InputStream in = new FileInputStream("c:\\q.txt");
byte[] b = new byte[32];
int size = in.read(b);
while(size!=-1){
//下面这样会有很多乱码。
System.out.print(new String(b, 0, size));
//如果我把q.txt保存为UTF-8,然后象下面这样构造String, 乱码没了。
//但是有少量问号
//System.out.print(new String(b, 0, size, "UTF-8"));
size = in.read(b);
}
in.close();
}
}q.txt是一个简单的中文文本文件。比如:进行被过滤黑名单的更新
。同时会另外启用两个xnet2.ex
e线程,与211.161.1.134 和 203.171.
236.231进行通讯,后者ip为 河南郑州景安计算机网络 ,前者
是北京  长宽的一个ip,具体来源不明。
坝完美得全部符合。它的存在真的是为了保护未成人收到色情网站
的毒害吗?未必,监视大量应用程序,定时对系统进行截图,对代理软
件进行封锁,然后将用户电脑中的各种资料秘密传往某处。问题我已经描述在程序中了, 怎么可以消除这样的问题,
还有就是在像这样的InputStream中,我不知道那个文件保存为什么样的编码, 我要把它用流读出来,然后显示出来,怎么做才没有乱码。
不要告诉我用BufferedReader.
如果愿意就byte, char,字节流,字符流做一些讨论和指导更好。
谢谢热心的朋友们。

解决方案 »

  1.   

    答:在JDK的早期,只有字节流,没有字符流。全是通过桥类InputStreamReader进行字节到字符的解码用的。
    楼主的问题,其实又回到了JDK的早期了:即只有字符流,怎样正确回到字符流?
    正常做法:
    1)字节流读取BOM,若有则按BOM的编码进行字符流的解析。
    2)若没有BOM,则只能猜测字节流是什么字符编码了(GBK?GB2312-80?等等),WIN下的WORD直到现在还是这样嘛“若无BOM,则询问使用者:文件是何编码?(默认是平台的默认编码:WIN是GBK,LINUX下是UTF-8)
    3)只有知道了编码,才好用桥类InputStreamReader进行最后的字符解码的读取。
      

  2.   

    楼主的问题,其实又回到了JDK的早期了:即只有字节流,怎样正确回到字符流? 
      

  3.   

    jiangnaisong:我的socket读取post的问题还有一点问题,帮忙看看吧。
    http://topic.csdn.net/u/20090625/22/59a5bfc8-a6b6-445d-9829-ea6d462a4fe6.html?seed=1942058963
      

  4.   

    答:另外:System.out.print(new String(b, 0, size));这段代码有问题。
    可能第size与size+1之间才能构成一个字符,若这样就分柝了,会有乱码的。
      

  5.   

    对, 这点太关键了。
    是不是说ANSI编码的话,有一些字符占一个字节,(像ascii范围内的) 有的占用2个?(像汉字)
      

  6.   

    一次性全读进来就没有问题了:import java.io.*;
    public class TestStream {
        public static void main(String[] args) throws Exception{
            //q.txt带有中文和中文特有的标点符号。保存为ANSI编码格式
            InputStream in = new FileInputStream("c:\\q.txt");
            byte[] b = new byte[640];        int size = in.read(b);
            BufferedOutputStream bos=new BufferedOutputStream(System.out);
            while(size!=-1){
                //下面这样会有很多乱码。
                System.out.print(new String(b, 0, size));
                //如果我把q.txt保存为UTF-8,然后象下面这样构造String, 乱码没了。
                //但是有少量问号
                //System.out.print(new String(b, 0, size, "UTF-8"));
                //bos.write(b,0,32);
                size = in.read(b);
            }
            in.close();
        }
      

  7.   

    呵呵
    总结一下吧
    1. 如果用字节流不包装的话,又不知道对方的编码,是没有办法的,只能按规律来
    2. LZ有的解出是问好的,估计是拆分了字符导致的,和System.out.print(new String(b, 0, size));有关系
       解决的办法是可以整文读取,放到内存,但是这样如果文件很大,会不会好呢,会不会有其它的办法呢,关注!!
    3. 其实现在的jdk已经针对以前字节流的不足,补充了很多包装类,LZ应该针对不同的应用环境来选择使用的
      

  8.   

    文本文件中,前N个字节(每种编码不一样)标识了本文件的字符编码ansi = 无(即第一个字节就是文件的内容)UTF-8 = 0xEF,0xBB,0xBF(UTF-8占用前3个字节)Unicode = 0xFF 0xFE(unicode占用前2个字节)附测试代码:/**
     * Title: CatchFileEncoding.java<br>
     * Description:获取文件字符集<br>
     * Copyright @ 2006  .All rights reserved.<br>
     * @author LiN
     * @version 2009-2-4 1.0
     */
    public class CatchFileEncoding { private static void test(InputStream is) throws IOException{
    BufferedInputStream bis = new BufferedInputStream(is);
    BufferedReader br = null;
    byte[] fileHead = new byte[3];
    try {
    bis.(0);
    bis.read(fileHead, 0, fileHead.length);
    bis.reset();
    if(checkEncoding(fileHead)==1){
    br = new BufferedReader(new InputStreamReader(bis,"UTF-8"));
    }
    // JDK5好像没有支持Unicode的Charset
    // else if(checkEncoding(fileHead)==2){
    // br = new BufferedReader(new InputStreamReader(bis,"UNICODE-1-1"));
    // }
    else{
    br = new BufferedReader(new InputStreamReader(bis));
    }
    System.out.println(br.readLine());
    } catch (IOException e) {
    e.printStackTrace();
    }finally{
    br.close();
    }
    for(int i=0;i<fileHead.length;i++){
    System.out.print(fileHead[i] + " ");
    }
    // String line = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(fileHead))).readLine();
    // System.out.println(line);
    System.out.println();
    }
    //利用读取文件前3个字节判断是否为UTF-8字符集(-17-69-65)(0xEF,0xBB,0xBF)
    //Unicode(-1 -2)(0xFF 0xFE)
    private static int checkEncoding(byte[] fileHead){
    final int UTF_8 = 1;
    final int UNICODE = 2;
    final int DEFAULT_ENCODING = 3;
    if(fileHead==null || fileHead.length<3)
    throw new RuntimeException("exception");//这里可抛出数据体不完整异常
    if((fileHead[0] & 0xFF)==0xEF && (fileHead[1] & 0xFF)==0xBB && (fileHead[2] & 0xFF)==0xBF)
    return UTF_8;
    if((fileHead[0] & 0xFF)==0xFF && (fileHead[1] & 0xFF)==0xFE)
    return UNICODE;
    return DEFAULT_ENCODING;
    }

    public static void main(String[] args) throws IOException {
    //System.out.println(Charset.availableCharsets());

    String[] txtFileNameArray = new File(CacheFileEncoding.class.getResource("").getPath()).list(new FilenameFilter(){
    public boolean accept(File dir, String name) {
    if("txt".equals(name.split("\\.")[1]))
    return true;
    return false;
    }
    });
    for(int i=0;i<txtFileNameArray.length;i++){
    System.out.print(txtFileNameArray[i] + "-->");
    test(CacheFileEncoding.class.getResourceAsStream(txtFileNameArray[i]));
    System.out.println();
    }
    }
    }
      

  9.   

    你自己说的//q.txt带有中文和中文特有的标点符号。保存为ANSI编码格式本来这个文件全是字符,也就是2个字节为一个字符,你用字节流读取显然不合适,加个转换流,再去试试FileReader read = new FileReader(new InputStreamReader(new FileInputStream("c:\\q.txt")));
      

  10.   

    没说完,或者你直接用字符流来读

    InputStreamReader read = new InputStreamReader("c:\\q.txt");
    BufferedReader br = new BufferedReader(read);
      

  11.   

    这是因为在txt文件(以GB2312)存储的的内容,汉字是两个字节的编码,对于数字和英文空格,则是一个字节编码,导致
    出现了问题,因为你每次读取的是32个字节,导致错误,我换了输出:发现如下:32
    进行被过滤黑名单的更新。同时会另
    32
    外启用两个xnet2.exe线程,与211.1
    32
    61.1.134 和 203.171.236.231进行?//这一行导致通讯的“通”字出现了问题,所以出现了乱码
    32
    ㄑ叮笳遡p为 河南郑州景安计算机
    32
    网络 ,前者是北京  长宽的一个ip?
    32
    咛謇丛床幻鳌0油昝赖萌糠稀
    32
    K拇嬖谡娴氖俏吮;の闯扇耸盏
    32
    缴橥镜亩竞β穑课幢兀嗍哟罅
    32
    坑τ贸绦颍ㄊ倍韵低辰薪赝迹
    32
    源砣砑蟹馑缓蠼没У缒
    29
    灾械母髦肿柿厦孛艽炒Α?-1
      

  12.   

    用"InputStreamReader(InputStream, String) " 应该可以解决楼主的问题,现在没环境测试,回去测试下.
    楼主说"不要告诉我用BufferedReader. " 是撒意思啊?
      

  13.   

    意思是我想探讨怎么把字节转为字符, 所以BufferedReader就跑题了撒。
      

  14.   

    楼主,建议你先设置一下流的编码:InputStreamReader(InputStream in, String charsetName);
      

  15.   

    看楼主的代码。
    貌似像是接触字符编码处理时间比较短暂。一般情况下,我们就用固定编码形式来处理字节流。
    如果发现乱码,就更改配置文件,换一个编码试一试。如果,程序非要完成编码的自动识别。这个问题就非常有难度了。
    通常的办法,就是逐个的将已知的编码逐个去试,能解码成功的就OK。
    这方面做的比较好的,mozilla基金会有一个Firefox用来自动探测编码的库
    LZ可以参看一下它的使用方式。
    其他方面的我就不知道了。我一般遇到这种情况,都是按照固定编码的方式来做的。
    只是,先使用GBK解码试试,不行再换UTF-8试试,都不行,就程序停止。
    InputStream is = ....;
    InputStreamReader isr = new InputStreamReader(is,"GBK");
    如果代码有异常,就重新获取InputStream , 然后InputStreamReader isr = new InputStreamReader(is,"UTF-8");
    当然,如果无法重新获取InputStream 的情况下,
    貌似有个ByteArrayInputStream的类,可以先把字节流存到这里,然后再使用。
      

  16.   

    以前是没有研究过编码,通常的做法就是凡是涉及到编码的地方都utf-8.
    因为写一段代码引起了我对编码和字符集的兴趣。
    http://blog.csdn.net/sunxing007/archive/2009/06/29/4305956.aspx
    这篇文章中, 解析http头需要用字节流,但是http头是有含义的,所以要把读到的http头的一行转换为字符串。
    于是我想顺便探讨一下子节流转字符流的问题。
      

  17.   

    System.out.print(new String(b.getBytes("GBK), 0, size));这样行不行?