Java字节流和字符流的转换器:StreamDecoder

来源:互联网 发布:centos 局域网断网 编辑:程序博客网 时间:2024/05/21 09:33

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

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

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

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


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

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

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

[java] view plaincopy
  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.   
  27.     // 由上述的 forInputStreamReader方法的参数可知用的是下面这个方法  
  28.     public static StreamDecoder forInputStreamReader(InputStream in,Object lock,String charsetName) throws UnsupportedEncodingException {  
  29.         String csn = charsetName;  
  30.        if (csn == null// 由于用的是默认编码,会执行这句  
  31.        csn = Charset.defaultCharset().name();  
  32.        try {  
  33.         if (Charset.isSupported(csn))   // 检测JVM是否支持该编码集  
  34.                   
  35.               return new StreamDecoder(in, lock, Charset.forName(csn));  
  36.        } catch (IllegalCharsetNameException x) { }  
  37.               throw new UnsupportedEncodingException (csn);  
  38.     }  
  39.       
  40.     StreamDecoder(InputStream in, Object lock, Charset cs) {  
  41.         this(in, lock, cs.newDecoder().onMalformedInput(CodingErrorAction  
  42.                         .REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE));  
  43.         // 额,说明它是在用Charset对象产生CharsetDecoder对象,目的是为了执行另一个构造函数  
  44.     }  
  45.   
  46.     StreamDecoder(InputStream in, Object lock, CharsetDecoder dec) {  
  47.         //  CharsetDecoder:是一个引擎,可以将一个字节序列按照特定的字符集转换成一个16位的Unicode序列  
  48.              super(lock);  
  49.              this.cs = dec.charset();  
  50.              this.decoder = dec;  
  51.         // 下面的代码先不用管,我们这里用不上  
  52.              // This path disabled until direct buffers are faster  
  53.              if (false && in instanceof FileInputStream) {  
  54.                     ch = getChannel((FileInputStream)in);  
  55.                     if (ch != null)  
  56.                         bb = ByteBuffer.allocateDirect(DEFAULT_BYTE_BUFFER_SIZE);  
  57.                 }  
  58.                 if (ch == null) {  
  59.                     this.in = in;  
  60.                     this.ch = null;  
  61.                     bb = ByteBuffer.allocate(DEFAULT_BYTE_BUFFER_SIZE);  
  62.                 }  
  63.                 bb.flip();                      // So that bb is initially empty  
  64.     }  
  65.     // 调用的就是这个函数吧  
  66.     public int read() throws IOException {  
  67.         return read0(); //额,又是假的;继续看  
  68.     }  
  69.     private int read0() throws IOException {  
  70.         synchronized (lock) {  
  71.             // Return the leftover char, if there is one  
  72.             if (haveLeftoverChar) {  
  73.                 haveLeftoverChar = false;  
  74.                 return leftoverChar;  
  75.             }  
  76.             // Convert more bytessz  
  77.             char cb[] = new char[2];    //一次读两个字节  
  78.             int n = read(cb, 02);  
  79.             switch (n) {  
  80.                 case -1:  
  81.                     return -1;  
  82.                 case 2:  
  83.                     leftoverChar = cb[1];  
  84.                     haveLeftoverChar = true;  
  85.                 // FALL THROUGH  
  86.                 case 1:  
  87.                     return cb[0];  
  88.                 default:  
  89.                     assert false : n;  
  90.                     return -1;  
  91.             }// end of catch  
  92.         }// end of  synchronized  
  93.     }  
  94.   
  95. }  

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

OutputStreamWrite编码过程中就有另外一个重要的类:StreamEncoder负责编码
0 0
原创粉丝点击