首页 > 编程知识 正文

java基础知识详解,java基础知识选择题

时间:2023-05-05 02:11:21 阅读:49461 作者:2380

一.缓冲写入器流API文档说明:

1 )将文本写入字符输出流,缓冲字符,有效写入各个字符、数组和字符串?

说明如何使用单个字符、数组和字符串作为参数写入数据

2)可以指定缓冲区大小,或者可以接受默认大小。对于大多数用途,默认值足够大?

表示此类具有常量值作为缺省缓冲区大小,也可以在构造函数中指定大小

3)提供了一个newLine()方法,它使用平台自己的行分隔符概念,由系统属性line.separator定义。并非所有平台都使用换行符(' n')来终止行。因此,调用此方法终止每个输出行比直接编写换行符更为可取。

输出时执行换行操作,并自动应用平台换行分隔符,因此更灵活,而不是自定义

4) 通常,Writer会立即将其输出发送到基础字符或字节流。除非需要提示输出,否则建议将BufferedWriter包装在任何write()操作可能代价高昂的Writer周围,例如FileWriters和OutputStreamWriters。

这意味着可以在缓冲写入器中包装write的子类以提高输出效率

二、缓冲写入器流实例区域可以看出存在一个默认字符缓冲区,且默认大小是8192个字符

//字符输出流私有写入器输出; //字符缓冲区专用char CB [ ]; //设定的文字缓冲区大小变量private int nChars; //字符缓冲区中已存储元素的位置private int nextChar; //默认字符缓冲区大小privatestaticintdefaultcharbuffersize=8192; /** *行分割字符串- * propertyatthemomentthatthestreamwascreated.*/privatestringlineseparator; 三、缓冲写入器流构造函数1、参数Writer out实际是Writer的子类如FileWriters和OutputStreamWriters等

2、 参数sz就是用于指定字符缓冲区大小的变量

/** * *默认字符缓冲区大小的构造函数* * @ paramoutawriter */publicbufferedwriter (writer out ) this(out,defaultCharBufferSize } /** *指定字符缓冲区大小的构造函数*/publicbufferedwriter (writer out,int sz ) super ) out; if(SZ=0) thrownewillegalargumentexception (' buffer size=0' ); this.out=out; cb=new char[sz]; nChars=sz; nextChar=0; line separator=Java.security.access controller.do privileged (news un.security.action.getproperty action (line.seses )

/** *写入字符并存储在字符缓冲区中的* * @ exceptionioexceptionifani/oerroroccurs */public void write (intc ) throwsioexception (同步)同步CB[nextchar]=(char ) c; //1字符} } 1)写一个字符到字符缓冲区中:本质是写入字符到字符缓冲区中

buf, off, len)方法而OutputStreamWriter的write(cbuf, off, len)方法实际是调用StreamEncoder的write方法执行的

     1、传入字符数组cbuf,字符数组的偏移点off,以及要写入的字符个数len--代表要从字符数组cbuf中下标off开始写入len个字符

     2、 前期条件判断避免出现RuntimeException异常所以必须抛出

     3、 当要写入的字符个数len大于字符缓冲区的长度时则意味着就算字符缓冲区cb是空的也无法载入写入字符,那么就没必有调用字符缓冲区了,直接调用write(cbuf, off, len)方法,out变量是OutputStreamWriter的对象,而OutputStreamWriter内的方法都是StreamEncoder类的方法执行。因此实际调用的是StreamEncoder的write方法。在StreamEncoder中直接把字符数组cbuf通过编码器编码到StreamEncoder的字节缓冲区中

    4、当要写入的字符个数len小于字符缓冲区的长度时,通过 System.arraycopy的方法把字符数组cbuf内要写入的字符复制到字符缓冲区cb中,其中while循环的作用就是保证符数组cbuf内要写入的字符全部复制到字符缓冲区cb中

* 写一个字符数组的一部分 * */ public void write(char cbuf[], int off, int len) throws IOException { synchronized (lock) { ensureOpen(); if ((off < 0) || (off > cbuf.length) || (len < 0) || ((off + len) > cbuf.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return; } if (len >= nChars) { //如果请求长度超过输出缓冲区的大小则直接进行输出,而不用字符缓冲区做缓冲 flushBuffer(); out.write(cbuf, off, len); //实际是调用的OutputStreamWriter的write方法本质是调用StreamEncoder的write方法执行的 return; } int b = off, t = off + len; //此循环的目的就是保证len个字符务必被复制到字符缓冲区中区 while (b < t) { int d = min(nChars - nextChar, t - b); //判断字符缓冲区中的剩余位置和要写入的字符长度最小值,若字符缓冲区空间充足,则复制len个字符,若不充足,则复制剩余位置个字符 System.arraycopy(cbuf, b, cb, nextChar, d); //从目标数组cbuf的下标b中复制d个字符到字符缓冲区 b += d; nextChar += d; if (nextChar >= nChars) //判断字符缓冲区是否已满?若满了,则调用flushBuffer方法把缓冲区中的内容全部输出,然后按道理此时字符缓冲区应该就是空了的? flushBuffer(); } } }

3)写字符串的一部分:本质跟第二个写字符数组的一部分一致

/** * 写一个字符串的一部分 * 若len为负值,则没有任何字符被写入, */ public void write(String s, int off, int len) throws IOException { synchronized (lock) { ensureOpen(); int b = off, t = off + len; while (b < t) { int d = min(nChars - nextChar, t - b); s.getChars(b, b + d, cb, nextChar); //本质跟System.arraycopy(cbuf, b, cb, nextChar, d);一样,将内容复制 到缓冲区中 b += d; nextChar += d; if (nextChar >= nChars) flushBuffer(); } } }

4)close方法--关闭流资源,关闭之前会先调用flushBuffer()方法然后调用StreamEncoder的write方法把字符缓冲区的内容写入到StreamEncoder的字节缓冲区中,最后调用close方法在把StreamEncoder的字节缓冲区内容输出到计算机中

/** * 关闭流,关闭之前先刷新缓冲区,然后再关闭流 */ public void close() throws IOException { synchronized (lock) { if (out == null) { return; } try { flushBuffer(); } finally { out.close(); //实际调用的是OutputStreamWriter的close方法 out = null; cb = null; } } } /** * 将字符缓冲区中的内容写入到字节缓冲区中 */ void flushBuffer() throws IOException { synchronized (lock) { ensureOpen(); if (nextChar == 0) return; out.write(cb, 0, nextChar); //注意这里的方法调用到了实现类outputSteam类的write方法 nextChar = 0; } }

5)flush方法:刷新缓冲区数据,其本质是先调用flushBuffer方法把BufferedWriter类中的字符缓冲区内容写入到StreamEncoder的字节缓冲区,而后调用OutputStreamWriter的flush方法把StreamEncoder的字节缓冲区内容给写出去,因此和close方法作用一致,但是没有关闭资源链接达到释放资源作用,所以项目中一般是先进行flush工作保证字节输出,而后调用close做二次保证以及关闭资源

/** * 刷新缓冲区将缓冲区字符编码到字节缓冲区中 * * @exception IOException If an I/O error occurs */ public void flush() throws IOException { synchronized (lock) { flushBuffer(); out.flush(); } } 五、BufferedWriter流与OutputStreamWriter的关系

     1)前面OutputStreamWriter的API说明中提到过:为了获得最高效率,请考虑在BufferedWriter中包装OutputStreamWriter,以避免频繁的转换器调用这句话,理解如下:

         当我们直接使用OutputStreamWriter进行输出时,不管是一个字符,还是一个数组,都会调用字符编码器进行转换,因为其是直接调用的StreamEncoder的implWrite方法,若存在for循环100次,每次调用write(int c)方法写入一个字符,那么最终就会调用100次的implWrite方法,就会调用100次的字符编码器进行转换

       但是当我们使用BufferedWriter包装OutputStreamWriter时,每次调用write(int c)方法时,都只是将字符写入到BufferedWriter类的字符缓冲区中。到最后调用flush方法或者close方法时,才会调用一次StreamEncoder的implWrite方法,也就是调用一次字符编码器

      因此BufferedWriter可以提高字符输出的效率,提高的关键点在于:存在字符缓冲区用于存储字符

 

2)因此根据对FileWriter、OutputStreamWriter、StreamEncoder、BufferedWriter的源码分析,我们可以得出以下几点

     2.1    以上4个类的起到字符编码成字节并调用底层字节输出流的是StreamEncoder类

    2.2     FileWriter类和OutputStreamWriter类只是傀儡性质,实际并未发挥作用

    2.3     项目中遇到文件字符输出流时,请使用BufferedWriter包装OutputStreamWriter类,以便提高效率

    2.4    StreamEncoder类在jdk1.7的版本中是没有源码可以导入的,因此不建议直接使用

    2.5    若要理解透彻,可以对以上4个类源码进行重写,然后做实际数据验证,就可以理解每一个方法的作用了

   

    

 

 

 

     

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。