本帖最后由 zhangjinyu1991 于 2013-2-20 16:46 编辑
今天在找StreamDecoder类的讲解没找到,就自己探索了一下,和大家分享分享:
字符与字节的转换
我们的机器只会读字节码,而我们人却很难读懂字节码,所以人与机器交流过程中需要编码解码。
InputStreamReader及其子类FileReader:(从字节到字符)是个解码过程;
OutputStreamWrite及其子类FileWriter:(从字符到字节)是个编码过程。
图片:(点这里)
现在对于这张图我们还有个难点没有解决: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 one
- if (haveLeftoverChar) {
- haveLeftoverChar = false;
- return leftoverChar;
- }
- // Convert more bytes
- 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
- }
- }
复制代码 |
|