Java基础13-字符串缓冲流;字节流

作业解析

  1. 描述HashMap内部实现原理
    HashMap是一种存储机制,存储的是key-value对,key用来保证元素的唯一性。通过hash算法将要存储的对象打散,分布在不同的区间中。
    • 当添加对象时,先得到该对象的hashcode,通过hashcode定位到将要存储的区间上,然后将区间中原有的元素依次与该对象进行比对,比对原则有三个:hashcode是否相同、是否是同一对象、equals方法是否返回true。如果没有元素与之相同,则添加到该区间元素的末尾
    • 通过key查询时,先得到key对应的hashcode, 然后定位到所在区间,简化了查询,最后按照上述的三个原则进行比对
  2. List Set Map区别
    • List
      ArrayList: 有序,可重复,线程不安全
      LinkedList: 手拉手,线程不安全
      Vector: 线程安全

    • Set
      HashSet: 不可重复,无序,使用键值对存储机制
      TreeSet: 通过实现Comparable接口实现排序,或者包装一个对比器Comparator
    • Map
      HashMap: 键值对,不可重复
      HashTable: 线程安全

  3. 描述HashSet和HashMap的区别
    HashSet集合内部是通过HashMap进行实现的。使用的是HashMap中key部分。对象在添加进集合中时,首选会对hashcode进行处理(hashcode右移16位和自身做异或运算)得到一个经过处理的hash值,然后该值和集合的容量进行&运算,得到介于0和集合容量值之间一个数字。该数字表示着数组的下标。也就是该元素应该存放在哪个集合中。然后按照hashcode1()==hashcode2() && (是否同一对象 || equals() )与集合中已有元素进行对比,如果没有相同的元素,则添加该元素。

  4. 编程实现文本文件的复制。合理设计程序,得到缓冲区的大小的高效区间。
    提示缓冲区设置1k开始,不超过10M。

     public static void main(String[] args) throws Exception {
    
         FileWriter fw = new FileWriter("Test.txt");
         int count=0;
         for(int i=0;i<=10000000;i++) {
             if(count<=1000) {
                 count++;
                 fw.write(i+",");                
             }
             else {
                 fw.write("\r\n");
                 count=0;
             }
         }
         fw.close();
         System.out.println("over");
    
         /*
          * 编程实现文本文件的复制。合理设计程序,得到缓冲区的大小的高效区间。
          * 提示:缓冲区设置1k开始,不超过10M。
          * */
    
         int bufSize=1024;//缓冲区1k开始
         long spendTime = 0;//耗费的时间
         long minTime = Long.MAX_VALUE;//记录最少耗时
         for(int i=1;i<=10*1024;i++) {
             long beginTime = System.currentTimeMillis();
             copyFile("Test.txt","Test2.txt",i*bufSize);
             spendTime = System.currentTimeMillis()-beginTime;
             if(spendTime<minTime) {
                 minTime = spendTime;
                 System.out.println(i);
             }
         }
         System.out.println(minTime);
         System.out.println("over");
     }
     /*
      * 按给定的缓冲区大小,复制文件src到des
      */
     public static void copyFile(String src,String des,int bufSize) throws Exception {
         FileReader fr = new FileReader(src);
         FileWriter fw = new FileWriter(des);
         char[] buf = new char[bufSize];
         int len = -1;
         while((len=fr.read(buf))!=-1) {
             fw.write(new String(buf,0,len));
         }
         fw.close();
         fr.close();
     }
  5. 使用FileWriter,将1-1000000写入到文本中

     package com.kokojia.io;
    
     import java.io.FileWriter;
     import java.io.IOException;
    
     public class FileWriterDemo {
    
         public static void main(String[] args) {
             /**
              * 使用FileWriter,将1-1000000写入到文本中
              */
             FileWriter fw = null;
             try {
                 fw = new FileWriter("h1.txt");
                 for(int i=1;i<=1000000;i++) {
                     fw.write(i+",");
                 }
             } catch (IOException e) {
                 e.printStackTrace();
             }
             finally {
                 if(fw!=null) {
                     try {
                         fw.close();
                     } catch (IOException e) {
                         e.printStackTrace();
                     }               
                 }
             }
             System.out.println("over!");
         }
     }
  6. 变长参数 + 增强for循环

     package com.kokojia.io;
    
     public class AvgParAndForDemo {
    
         public static void main(String[] args) {
             /**
              * 变长参数 + 增强for循环练习
              */
             OutString("a","b","123","中国");
    
         }
    
         //变长参数只能有一个,且必须是最后一位形参
         private static void OutString(String...str) {
             for(String s: str) {
                 System.out.println(s);
             }
         }
    
     }

行分隔符在java中可以通过方法得到

System.getProperty("line.separator"); //执行 系统属性名
系统属性名是line.separator
windows: \r\n
macOS: \n

字符缓冲区

  1. FileWriter没有缓冲区功能,本身没有新增任何功能,继承的OutputStreamWriter
    • 等级树结构:Object ---> Writer ---> OutputStreamWriter ---> FileWriter

        writer(){
         //直接写入数据到文件中
        sun.nio.cs.StreamEncoder.write();
        }
  2. FileReader
    • 继承关系树:Object ---> Reader ---> InputStreamReader ---> FileReader
    • read()
      读取一个字符
    • read(char[])
      读取多个字符

        read(){
            InputStreamReader.read(){
                sun.nio.StreamDecoder.read();
            }
        }
  3. BufferedReader
    • 等级树结构:Object ---> Reader ---> BufferedReader ---> LineNumberReader

        read(){
            char[] cbuf = ... ;
            cbuf[xxx] = c;
            return c;
        }
    • 避免对物理文件的频繁访问

        public static void main(String[] args) throws Exception {
                BufferedReader bufReader = new BufferedReader(new FileReader("d:/foo.txt"));
                String line = null;
                while((line = bufReader.readLine())!=null) {
                    System.out.println(line);
                }
                System.out.println("over");
                bufReader.close();
      
                /*
                 * 使用LineNumberReader读取文件的行号
                 * 打印输出行号+"."+行内容
                 */
                LineNumberReader lineNumReader = new LineNumberReader(new FileReader("d:/foo.txt"));
                while((line=lineNumReader.readLine())!=null) {
                    int lineNo = lineNumReader.getLineNumber();
                    System.out.println(lineNo+"."+line);
                }
                lineNumReader.close();
                System.out.println("------------");
      
                /**
                 * 使用FileReader和BufferedReader读取文本文件,观察消耗时间
                 */
                //非缓冲reader
                FileReader fr = new FileReader("d:\\1.txt");
                //缓冲reader
                BufferedReader br = new BufferedReader(new FileReader("d:\\1.txt"));
      
                //非缓冲循环读取
                int len = -1;
                //开始时间
                long beginTime = System.currentTimeMillis();
                while((len=fr.read())!=-1) {
                }
                //结束时间
                long endTime = System.currentTimeMillis();
                fr.close();
                System.out.println("reader over!花费了时间"+(endTime-beginTime));//42443
      
                //缓冲循环读取
                beginTime = System.currentTimeMillis();
                while((len=br.read())!=-1) {
                }
                //结束时间
                endTime = System.currentTimeMillis();
                br.close();
                System.out.println("bufreader over!花费了时间"+(endTime-beginTime));//18654
            }
  4. BufferedWriter
    • 对Writer进行包装,里面定义缓冲区,提供写入单个字符、char[]、String方法,提高写入效率
    • 等级树结构:Object ---> Writer ---> BufferedWriter
    • flushBuffer(): 清理缓冲区,将缓冲区数据写入目的地
    • close()方法: 包含flushBuffer()动作

           static char[] buf = null;
           static {
                  buf = new char[8192];
                  for(int i=0;i<8192;i++) {
                         buf[i]='a';
                  }
      
           }
           public static void main(String[] args) throws Exception {
      
                  PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("d:/foo.txt"))); 
                  out.println("hello word");
                  out.close();
                  System.out.println("over");
      
                  //非缓冲
                  FileWriter fw = new FileWriter("d:/1.txt");
                  //缓冲区
                  BufferedWriter bw = new BufferedWriter(new FileWriter("d:/2.txt"),1024*1024);
      
                  /**************非缓冲区writer操作*******/
                  //最大次数
                  int max = 100000;
                  //开始时间
                  long startTime = System.currentTimeMillis(); 
                  for(int i=0;i<max;i++) {
                         fw.write(buf);
                  }
                  fw.close();
                  long endTime = System.currentTimeMillis(); 
                  System.out.println("wrtier over! 花费了时间:"+(endTime-startTime));
      
                  /**************缓冲区writer操作*******/
                  //开始时间
                  startTime = System.currentTimeMillis(); 
                  for(int i=0;i<max;i++) {
                         bw.write(buf);
                  }
                  bw.close();
                  endTime = System.currentTimeMillis(); 
                  System.out.println("bufwrtier over! 花费了时间:"+(endTime-startTime));
           }

内存回收机制

堆中的对象只有在没有引用时才会释放
byte[] bytes = new byte[1023][1024][1024];
byte[] b2 = bytes ;
.
.
.
.
bytes = null ;

几个重要的函数

  1. flush() //清理

  2. refresh() //刷新

  3. clear() //清空

字节流

  1. OutputStream
    • 输出流
    • FileOutputStream
    • 等级树: Object ---> OutputStream --->FileOutputStream
  2. InputStream
    • 输入流
    • FileInputStream
    • 等级树:Object ---> InputStream --->FileInputStream

装饰模式:decorator

实现方式: Buffered 类继承Writer类,在类中添加Writer类型的成员变量,对象应方法进行重写时,调用成员变量的方法进行完成。

 class BufferedWriter extends Writer{
   Writer out;
   char[] cb = new char[8192];
   public void writer(String str){
     //1.先将数据写入缓冲区
     cb.xxx
     //2.如果cb已满,再写入到out中
   }

   public void close(){
     //1.清理cb
     //2.关闭out
   }
 }

时间单位换算:
1s=1000ms
1ms=1000us
1us=1000ns

juint

  1. 单元测试框架
  2. 方便进行测试时使用
  3. 方法签名
import org.juint.Text
@Test
public void  xxx(){
}

作业

  1. 阐述BufferedReader和BufferedWriter的工作原理,
    是否缓冲区读写器的性能恒大于非缓冲区读写器的性能,为什么,请举例说明?
  2. 写入数据1~1000000数字到文件中,分别使用FileWriter和BufferedWriter实现,考察其效率的不同

  3. 文件切割:
    把较大的文件切割成20k一个的小文件
  4. 文件合成:
    把小文件合并成大文件

  5. 文件归档解档:
    0=txt,1=jpg,2=avi,3=gif

  6. Charset类操作: isSupport()
    • 通过该类验证平台是否支持一下字符集:
      gb2312
      GB2312
      gbk
      GBK
      utf-8
      utf8
      iso8859-1
      iso-8859-1

    • 取出平台默认的字符集

  7. FileReader.getEncoding();
    new String(,,,,,charset);

  8. 使用FileInputStream + FileOutputStream / BufferedInputStream + BufferedOuputStream
    实现大文件复制,比较复制效率。

  9. 阐述对象回收的前提条件。

上一篇:java – 为什么FileWriter没有创建新文件? FileNotFoundException


下一篇:java – 使用BufferedWriter将相同的数据写入多个文件