首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

黑马软件工程师 java IntputStreamRead把字节转为字符过程分析

2013-02-24 
黑马程序员 java IntputStreamRead把字节转为字符过程分析----------android培训、java培训、java学习型技术

黑马程序员 java IntputStreamRead把字节转为字符过程分析

----------android培训、java培训、java学习型技术博客、期待与您交流! ----------

我们的机器只会读字节码,而我们人却很难读懂字节码,所以人与机器交流过程中需要编码解码。

InputStreamReader及其子类FileReader:(从字节到字符)是个解码过程;

OutputStreamWrite及其子类FileWriter:(从字符到字节)是个编码过程。

InputStreamReader这个解码过程中,最主要的就是StreamDecoder类

黑马软件工程师 java IntputStreamRead把字节转为字符过程分析


    InputStream到Reader的过程要指定编码字符集,否则将采用操作系统默认字符集,很可能会出现乱码问题。(查看JDK中的InputStreamReader类的构造函数,除了第一个构造函数没有制定外,其他几个都需要指定)

    如果看不懂这个图请先看Association,Aggregation and Composition这篇文章。

    现在对于这张图我们还有个难点没有解决:StreamDecoder是个什么东西?这个,这个工作就有点复杂了,网上资料比较少,我自己找源码看看:

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 oneif (haveLeftoverChar) {haveLeftoverChar = false;return leftoverChar;}// Convert more bytesszchar cb[] = new char[2];//一次读两个字节int n = read(cb, 0, 2);switch (n) {case -1:return -1;case 2:leftoverChar = cb[1];  haveLeftoverChar = true;// FALL THROUGHcase 1:return cb[0];default:assert false : n;return -1;}// end of catch}// end of  synchronized}}

明白了是谁真正负责转换了吧,哈哈

OutputStreamWrite编码过程中就有另外一个重要的类:StreamEncoder负责编码

热点排行