黑马程序员技术交流社区

标题: InputStreamReader的编码是如何实现的 [打印本页]

作者: 张晋瑜    时间: 2013-2-20 16:20
标题: InputStreamReader的编码是如何实现的
本帖最后由 zhangjinyu1991 于 2013-2-20 16:46 编辑

今天在找StreamDecoder类的讲解没找到,就自己探索了一下,和大家分享分享:
字符与字节的转换
我们的机器只会读字节码,而我们人却很难读懂字节码,所以人与机器交流过程中需要编码解码。
InputStreamReader及其子类FileReader:(从字节到字符)是个解码过程;
OutputStreamWrite及其子类FileWriter:(从字符到字节)是个编码过程。
图片:(点这里)
现在对于这张图我们还有个难点没有解决:StreamDecoder是个什么东西?这个,这个工作就有点复杂了,网上资料比较少,我自己找源码看看:
  1. public class InputStreamReader extends Reader {
  2.     private final StreamDecoder sd;//由上图已知在InputStreamReader中一定有一个StreamDecoder对象
  3.         public InputStreamReader(InputStream in) {//InputStreamReader有多个构造方法,我假设它用的就是这个
  4.         super(in);
  5.         try {
  6.                           // 创建一个StreamDecoder对象
  7.             sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // 用系统默认编码
  8.         } catch (UnsupportedEncodingException e) {
  9.             // The default encoding should always be available
  10.             throw new Error(e);
  11.         }
  12.     }
  13.         public int read() throws IOException {
  14.                 // 看猫腻来了,竟然实际上是StreamDecoder在read
  15.         return sd.read();
  16.     }
  17. /**其他的方法我们不管,看有关的就行**/
  18. }
  19. 好,再来看看JDK7中的StreamDecoder(eclipse中显示不出,我也不知道为什么,我在这个网址看的源码点一下)是怎么实现的:
  20. public class StreamDecoder extends Reader{
  21.         private static final int MIN_BYTE_BUFFER_SIZE = 32;
  22.         private static final int DEFAULT_BYTE_BUFFER_SIZE = 8192;
  23.         private Charset cs;
  24.         private CharsetDecoder decoder;
  25.         private ByteBuffer bb;

  26.         // 由上述的 forInputStreamReader方法的参数可知用的是下面这个方法
  27.         public static StreamDecoder forInputStreamReader(InputStream in,Object lock,String charsetName) throws UnsupportedEncodingException {
  28.                 String csn = charsetName;
  29.        if (csn == null)        // 由于用的是默认编码,会执行这句
  30.        csn = Charset.defaultCharset().name();
  31.        try {
  32.                if (Charset.isSupported(csn))        // 检测JVM是否支持该编码集
  33.                                 
  34.               return new StreamDecoder(in, lock, Charset.forName(csn));
  35.        } catch (IllegalCharsetNameException x) { }
  36.               throw new UnsupportedEncodingException (csn);
  37.         }
  38.         
  39.         StreamDecoder(InputStream in, Object lock, Charset cs) {
  40.         this(in, lock, cs.newDecoder().onMalformedInput(CodingErrorAction
  41.                                                 .REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE));
  42.                 // 额,说明它是在用Charset对象产生CharsetDecoder对象,目的是为了执行另一个构造函数
  43.     }

  44.         StreamDecoder(InputStream in, Object lock, CharsetDecoder dec) {
  45.                 //  CharsetDecoder:是一个引擎,可以将一个字节序列按照特定的字符集转换成一个16位的Unicode序列
  46.              super(lock);
  47.              this.cs = dec.charset();
  48.              this.decoder = dec;
  49.              // 下面的代码先不用管,我们这里用不上
  50.              // This path disabled until direct buffers are faster
  51.              if (false && in instanceof FileInputStream) {
  52.                              ch = getChannel((FileInputStream)in);
  53.                              if (ch != null)
  54.                                  bb = ByteBuffer.allocateDirect(DEFAULT_BYTE_BUFFER_SIZE);
  55.                      }
  56.                      if (ch == null) {
  57.                              this.in = in;
  58.                              this.ch = null;
  59.                              bb = ByteBuffer.allocate(DEFAULT_BYTE_BUFFER_SIZE);
  60.                      }
  61.                      bb.flip();                      // So that bb is initially empty
  62.         }
  63.         // 调用的就是这个函数吧
  64.         public int read() throws IOException {
  65.                 return read0(); //额,又是假的;继续看
  66.         }
  67.         private int read0() throws IOException {
  68.                 synchronized (lock) {
  69.                         // Return the leftover char, if there is one
  70.                         if (haveLeftoverChar) {
  71.                                 haveLeftoverChar = false;
  72.                                 return leftoverChar;
  73.                         }
  74.                         // Convert more bytes
  75.                         char cb[] = new char[2];        //一次读两个字节
  76.                         int n = read(cb, 0, 2);
  77.                         switch (n) {
  78.                                 case -1:
  79.                                         return -1;
  80.                                 case 2:
  81.                                         leftoverChar = cb[1];
  82.                                           haveLeftoverChar = true;
  83.                                 // FALL THROUGH
  84.                                 case 1:
  85.                                         return cb[0];
  86.                                 default:
  87.                                         assert false : n;
  88.                                         return -1;
  89.                         }// end of catch
  90.                 }// end of  synchronized
  91.         }

  92. }
复制代码

作者: 张晋瑜    时间: 2013-2-20 16:22
额,没有办法传图




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2