zoukankan      html  css  js  c++  java
  • java IO(八):FileWriter和OutputStreamWriter和StreamEncoder

    其实这三个输出流,就是对应那三个输入流的。

    和那三个输入流一样,这三个流在字符输出上也密切相关。

    一、FileWriter

    和输入流一样,也是只有几个对应文件系统的构造方法,这里不再赘述。

    二、OutputStreamWriter

    和输入流一样,也是通过传入的OutputStream流对StreamEncoder进行初始化,append在OutputStream流中已指定。

    三、StreamEncoder

    这才是字符输出流的关键类(同理在实际使用中也最好使用BufferedWriter进行包装)

    这个类和StreamDecoder长得非常类似,我们来比较一下:

    1)属性域

        
    StreamEncoder
       private static final int DEFAULT_BYTE_BUFFER_SIZE = 8192; //确保流是打开状态否则无法输入输出 private volatile boolean isOpen; //字符集 private Charset cs; //编码器 private CharsetEncoder encoder; //字节缓冲区 private ByteBuffer bb; //输出流 private final OutputStream out; //信道,对于输入流,缓冲区从信道中取数据,对于输出流,缓冲区输出内容到信道(应该是这样,信道这个概念还未理解) private WritableByteChannel ch; //为保证读入的字符不乱吗,则每次要读入两个字符 private boolean haveLeftoverChar; private char leftoverChar; //字符缓冲区——专用于左侧字符操作 private CharBuffer lcb;
      
    StreamDecoder
      //
    定义两个表示字节缓冲区大小的整型常量,最小为32,默认为8192 private static final int MIN_BYTE_BUFFER_SIZE = 32; private static final int DEFAULT_BYTE_BUFFER_SIZE = 8192; //表示流是否被打开的布尔型变量 private volatile boolean isOpen; //在read里用到,read方法返回一个字符,但实际上是读取2个字符,剩余的一个字符会保存到leftoverChar里,haveLeftoverChar表示是否有这个剩余多出来的字符。 private boolean haveLeftoverChar; private char leftoverChar; //这个和下面的ReadableByteChannel意思是信道,但还不知道有什么用 private static volatile boolean channelsAvailable = true; //字符集 private Charset cs; //解码器 private CharsetDecoder decoder; //字节缓冲对象 private ByteBuffer bb; //字节输入流 private InputStream in; private ReadableByteChannel ch;

    2)构造方法

        private StreamEncoder(OutputStream var1, Object var2, Charset var3) {
            this(var1, var2, var3.newEncoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE));
        }
    
        private StreamEncoder(OutputStream var1, Object var2, CharsetEncoder var3) {
            super(var2);
            this.isOpen = true;
            this.haveLeftoverChar = false;
            this.lcb = null;
            this.out = var1;
            this.ch = null;
            this.cs = var3.charset();
            this.encoder = var3;
            if (this.ch == null) {
                this.bb = ByteBuffer.allocate(8192);
            }
    
        }
    
        private StreamEncoder(WritableByteChannel var1, CharsetEncoder var2, int var3) {
            this.isOpen = true;
            this.haveLeftoverChar = false;
            this.lcb = null;
            this.out = null;
            this.ch = var1;
            this.cs = var2.charset();
            this.encoder = var2;
            this.bb = ByteBuffer.allocate(var3 < 0 ? 8192 : var3);
        }

    和StreamDecoder区别不大,不再赘述

    3)forOutputStreamWriter()

        public static StreamEncoder forOutputStreamWriter(OutputStream var0, Object var1, String var2) throws UnsupportedEncodingException {
            String var3 = var2;
            if (var2 == null) {
                var3 = Charset.defaultCharset().name();
            }
    
            try {
                if (Charset.isSupported(var3)) {
                    return new StreamEncoder(var0, var1, Charset.forName(var3));
                }
            } catch (IllegalCharsetNameException var5) {
            }
    
            throw new UnsupportedEncodingException(var3);
        }
    
        public static StreamEncoder forOutputStreamWriter(OutputStream var0, Object var1, Charset var2) {
            return new StreamEncoder(var0, var1, var2);
        }
    
        public static StreamEncoder forOutputStreamWriter(OutputStream var0, Object var1, CharsetEncoder var2) {
            return new StreamEncoder(var0, var1, var2);

    也和StreamDecoder区别不大。

    4)write()

    相较StreamDecoder的read()方法,write()方法要简单许多,就是直接判断offset和len的合法性,然后调用implWrite()

    public void write(int var1) throws IOException {
            char[] var2 = new char[]{(char)var1};
            this.write((char[])var2, 0, 1);
        }
    
        public void write(char[] var1, int var2, int var3) throws IOException {
            synchronized(this.lock) {
                this.ensureOpen();
                if (var2 >= 0 && var2 <= var1.length && var3 >= 0 && var2 + var3 <= var1.length && var2 + var3 >= 0) {
                    if (var3 != 0) {
                        this.implWrite(var1, var2, var3);
                    }
                } else {
                    throw new IndexOutOfBoundsException();
                }
            }
        }
    
        public void write(String var1, int var2, int var3) throws IOException {
            if (var3 < 0) {
                throw new IndexOutOfBoundsException();
            } else {
                char[] var4 = new char[var3];
                var1.getChars(var2, var2 + var3, var4, 0);
                this.write((char[])var4, 0, var3);
            }
        }

    上下两个方法本质就是调用中间的write(char[] var1,int var2,int var3)

    对于最上面的方法,是将单个字符转成字符数组,然后传入中间方法;对于下面的方法,是将字符串转成字符数组,再传入中间方法。

    中间方法var1便是那个字符数组,var2可以理解为offset,var3可以理解为length。

    5)implWrite(char[] cbuf, int offset, int length)

    void implWrite(char[] var1, int var2, int var3) throws IOException {
            CharBuffer var4 = CharBuffer.wrap(var1, var2, var3);
            if (this.haveLeftoverChar) {
                this.flushLeftoverChar(var4, false);
            }
    
            while(var4.hasRemaining()) {
                CoderResult var5 = this.encoder.encode(var4, this.bb, false);
                if (var5.isUnderflow()) {
                    assert var4.remaining() <= 1 : var4.remaining();
    
                    if (var4.remaining() == 1) {
                        this.haveLeftoverChar = true;
                        this.leftoverChar = var4.get();
                    }
                    break;
                }
    
                if (var5.isOverflow()) {
                    assert this.bb.position() > 0;
    
                    this.writeBytes();
                } else {
                    var5.throwException();
                }
            }
    
        }

    flushLeftoverChar()和writeBytes()将在(八)中说到。

  • 相关阅读:
    约瑟夫问题的解法集锦
    java调用com组件将office文件转换成pdf
    hdu(1069)——Monkey and Banana(LIS变形)
    Unix网络编程之环境搭建
    atitit. java queue 队列体系and自己定义基于数据库的队列总结o7t
    怎样使Dialog像Activity一样随心所欲的使用?
    获取全部分组中某列最大的行
    Class C++
    spring mvc +Mybatis3.1 整合的时候异常
    Linux 编译C++ 与 设置 Vim
  • 原文地址:https://www.cnblogs.com/MYoda/p/11213191.html
Copyright © 2011-2022 走看看