您的当前位置:首页正文

InputStreamReader原理

2024-11-09 来源:个人技术集锦
我们的机器只会读字节码,而我们人却很难读懂字节码,所以人与机器交流过程中需要编码解码。
InputStreamReader及其子类FileReader:(从字节到字符)是个解码过程;【字节流转换成字符流】
OutputStreamWrite及其子类FileWriter:(从字符到字节)是个编码过程。
InputStreamReader这个解码过程中,最主要的就是 StreamDecoder
 
InputStream到Reader的过程 要指定编码字符集否则将采用操作系统默认字符集,很可能会出现乱码问题。(查看JDK中的InputStreamReader类的构造函数,除了第一个构造函数没有制定外,其他几个都需要指定)
如果看不懂这个图请先看Association,Aggregation and Composition这篇文章。
现在对于这张图我们还有个难点没有解决: StreamDecoder是个什么东西 ?这个,这个工作就有点复杂了,网上资料比较少,我自己找 看看:
[java]  
public class InputStreamReader extends Reader {  
    private final StreamDecoder sd;//由上图已知在InputStreamReader中一定有一个StreamDecoder对象  
    public InputStreamReader(InputStream in) {//InputStreamReader有多个构造方法,我假设它用的就是这个  
        super(in);  
        try {  
              // 创建一个StreamDecoder对象  
            sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // 用 默认编码  
        } catch (UnsupportedEncodingException e) {  
            // The default encoding should always be available  
            throw new Error(e);  
        }  
    }  
    public int read() throws IOException {  
        // 看猫腻来了,竟然 实际上是StreamDecoder在read  
        return sd.read();  
    }  
/**其他的方法我们不管,看有关的就行**/  
}  
好,再来看看JDK7中的StreamDecoder(eclipse中显示不出,我也不知道为什么,我在这个网址看的源码点一下)是怎么实现的:  
public class StreamDecoder extends Reader{  
    private static final int MIN_BYTE_BUFFER_SIZE = 32;  
    private static final int DEFAULT_BYTE_BUFFER_SIZE = 8192;  
    private Charset cs;  
    private CharsetDecoder decoder;  
    private ByteBuffer bb;  
  
    // 由上述的 forInputStreamReader方法的参数可知用的是下面这个方法  
    public static StreamDecoder forInputStreamReader(InputStream in,Object lock,String charsetName) throws UnsupportedEncodingException {  
        String csn = charsetName;  
       if (csn == null) // 由于用的是默认编码,会执行这句  
       csn = Charset.defaultCharset().name();  
       try {  
        if (Charset.isSupported(csn))   // 检测JVM是否支持该编码集  
                  
              return new StreamDecoder(in, lock, Charset.forName(csn));  
       } catch (IllegalCharsetNameException x) { }  
              throw new UnsupportedEncodingException (csn);  
    }  
      
    StreamDecoder(InputStream in, Object lock, Charset cs) {  
        this(in, lock, cs.newDecoder().onMalformedInput(CodingErrorAction  
                        .REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE));  
        // 额,说明它是在 用Charset对象产生CharsetDecoder对象,目的是为了执行另一个构造函数  
    }  
  
    StreamDecoder(InputStream in, Object lock, CharsetDecoder dec) {  
        //  CharsetDecoder:是一个引擎,可以将一个字节序列按照特定的字符集转换成一个16位的Unicode序列  
             super(lock);  
             this.cs = dec.charset();  
             this.decoder = dec;  
        // 下面的代码先不用管,我们这里用不上  
             // This path disabled until direct buffers are faster  
             if (false && in instanceof FileInputStream) {  
                    ch = getChannel((FileInputStream)in);  
                    if (ch != null)  
                        bb = ByteBuffer.allocateDirect(DEFAULT_BYTE_BUFFER_SIZE);  
                }  
                if (ch == null) {  
                    this.in = in;  
                    this.ch = null;  
                    bb = ByteBuffer.allocate(DEFAULT_BYTE_BUFFER_SIZE);  
                }  
                bb.flip();                      // So that bb is initially empty  
    }  
    // 调用的就是这个函数吧  
    public int read() throws IOException {  
        return read0(); //额,又是假的;继续看  
    }  
    private int read0() throws IOException {  
        synchronized (lock) {  
            // Return the leftover char, if there is one  
            if (haveLeftoverChar) {  
                haveLeftoverChar = false;  
                return leftoverChar;  
            }  
            // Convert more bytessz  
            char cb[] = new char[2];    //一次读两个字节  
            int n = read(cb, 0, 2);  
            switch (n) {  
                case -1:  
                    return -1;  
                case 2:  
                    leftoverChar = cb[1];  
                    haveLeftoverChar = true;  
                // FALL THROUGH  
                case 1:  
                    return cb[0];  
                default:  
                    assert false : n;  
                    return -1;  
            }// end of catch  
        }// end of  synchronized  
    }  
  
Top