欢迎光临散文网 会员登陆 & 注册

java文件字节流和字节缓冲流

2022-08-21 09:18 作者:虚云幻仙  | 我要投稿

/**
* 测试文件字节输入流和文件字节输出流
* FileInputStream/FileOutputStream是以字节为单位存取文件,可用于存取二进制文件(图片、视频)和文本文件等,当存取文本文件时,由于每次只存取1byte内容即8位二进制数,所显示的字符仅能对应0-255即ASCII码的部分
* 对于文本文件使用字符流Reader/Writer可以支持unicode字符集
*/

public class TestFileStream {
   public static void main(String[] args) {
       long startTime = System.currentTimeMillis();
       try (FileInputStream fis = new FileInputStream("iostream/a.jpg");FileOutputStream fos = new FileOutputStream("iostream/c.jpg")){
           //创建文件字节输入流对象,需要传入相对路径/绝对路径,当没有找到该文件时会报异常
           //try-with-resource在try()内用;号隔开多个声明

           for (int i = fis.read();i!=-1;i = fis.read()){
               fos.write(i);
           }
           fos.flush();
           //.flush()方法使已缓存的字节bytes立刻写入到目的地,如果目的地是底层操作系统的抽象abstraction比如文件file,则仅能将已缓存的字节传递给操作系统
           //.flush()的作用只是使写入操作更优先执行,不使用flush程序也会完成写入

       }catch (Exception e){
           e.printStackTrace();
       }
       //文件的存储都是使用二进制实现的,所以即便是文本文件,每一个字符也是使用字节存储的,所以read()方法返回的是字节即8位二进制数,这一步是没有经过任何解码的,仅是将8位二进制数转化为int显示出来,至于读出的字节如何解释、以及一个基础单元是由几个字节组成,都是在数据本身之外规定的
       long endTime = System.currentTimeMillis();
       System.out.println(endTime-startTime);
       //耗时3183ms
       //读一个字节写一个字节的方式需要频繁调用io操作,io设备的速度相比cpu和内存慢的多,频繁调用会使程序频繁等待io的响应造成耗时


       startTime = System.currentTimeMillis();
       byte[] buffer = new byte[1024];
       //创建一个缓冲区用来缓存read()的字节,每读取1024字节即1kb后执行一次write()
       try (FileInputStream fis = new FileInputStream("iostream/a.jpg");FileOutputStream fos = new FileOutputStream("iostream/b.jpg")){
           for (int len = fis.read(buffer);len!=-1;len = fis.read(buffer)){
               //.read(byte[])也会返回int,返回的数值为读取到byte[]数组中字节的数量,当文件没有读完时会将数组填满返回buffer.length(),当彻底读完会返回-1,当读了一部分将文件读完时返回实际读取到的数量
               fos.write(buffer,0,len);
               //.write(byte b[],int off,int len) ,off即offset偏移量,从0位开始写,写入长度为数组实际存放bytes的长度
           }
           fos.flush();
       }catch (Exception e){
           e.printStackTrace();
       }
       endTime = System.currentTimeMillis();
       System.out.println(endTime-startTime);
       //耗时6ms

       startTime = System.currentTimeMillis();
       try (FileInputStream fis = new FileInputStream("iostream/a.jpg");FileOutputStream fos = new FileOutputStream("iostream/d.jpg")){
           buffer = new byte[fis.available()];
           //.available()返回当前读取的剩余部分的预估长度,当前没有读取过所以返回的是文件大小/总长度的预估
//            System.out.println(buffer.length);
           //长度为517741
//            System.out.println(new File("iostream/a.jpg").length());
           //长度为517741
           fis.read(buffer);
           fos.write(buffer);
           fos.flush();
       }catch (Exception e ){
           e.printStackTrace();
       }
       endTime = System.currentTimeMillis();
       System.out.println(endTime-startTime);
       //耗时2ms
       //将文件一口气完全读取到内存,再一次性写入到目的地,这样做时间成本比分段拷贝更快,但需要占用更多内存,当文件过大时无法使用


       startTime = System.currentTimeMillis();
       try (FileInputStream fis = new FileInputStream("iostream/a.jpg");
            FileOutputStream fos = new FileOutputStream("iostream/e.jpg");
            BufferedInputStream bis = new BufferedInputStream(fis);
            BufferedOutputStream bos = new BufferedOutputStream(fos)){
           //BufferedInputStream/BufferedOutputStream缓冲字节流,内置了缓冲数组byte[8192],不能直接连接数据源,用来包装节点流或其他流,属于处理流,将节点流传入构造器中,通过缓冲流对象调用读写方法
           for (int nextB = bis.read();nextB!=-1;nextB = bis.read()){
               bos.write(nextB);
               //不需要传入数组,bis将文件内容读到内置的数组中,每次.read()返回的是数组中缓存的下一个字节,如果没读完返回0-255,如果读完了即之后没有内容了返回-1
                //bos.write(int)会将字节存到bos内置的数组中,当数组满了或其他调用了flush的情况下会执行数组的写入.write(byte[],offset,len)

           }
           bos.flush();
           //对执行写入的对象调用flush
       }catch (Exception e){
           e.printStackTrace();
       }
       endTime = System.currentTimeMillis();
       System.out.println(endTime-startTime);
       //结果22ms

   }
}

class CopyTool{
   //自定义拷贝工具类
   public static void copySrcToDes(String src,String des){
       //src数据源,des目的地
       FileInputStream fis = null;
       FileOutputStream fos = null;
       BufferedInputStream bis = null;
       BufferedOutputStream bos = null;
       try {
           fis = new FileInputStream(src);
           bis = new BufferedInputStream(fis);
           //先实例化节点流,再将节点流传给处理流构造器
           fos = new FileOutputStream(des);
           bos = new BufferedOutputStream(fos);

           for (int next = bis.read();next!=-1;next = bis.read()){
               bos.write(next);
           }
           bos.flush();
           System.out.println("拷贝完成");
       }catch (Exception e){
           e.printStackTrace();
       }finally {
           try {
               if (bos != null) {
                   bos.close();
               }
               if (fos != null) {
                   fos.close();
               }
               //后进先出
               if (bis != null) {
                   bis.close();
               }
               if (fis != null) {
                   fis.close();
               }
           }catch (Exception e){
               e.printStackTrace();
           }
       }
   }

   public static void main(String[] args) {
       CopyTool.copySrcToDes("iostream/a.jpg","iostream/f.jpg");
   }
}

java文件字节流和字节缓冲流的评论 (共 条)

分享到微博请遵守国家法律