zoukankan      html  css  js  c++  java
  • 相对内存的文件操作字节流

    字节流的概念

    在计算机中,无论文本、图片、音频还是视频,所有文件都是以二进制(字节)形式存在的。IO流中针对字节的输入输出提供了一系列的流,统称为字节流。字节流是程序中最常用的流,根据数据的传输方向可将其分为字节输入流和字节输出流。在JDK中,提供了两个抽象类InputStream和OutputStream,它们是字节流的顶级父类,所有的字节输入流都继承自InputStream,所有的字节输出流都继承自OutputStream。

    InputStream被看成一个输入管道,OutputStream被看成一个输出管道,数据通过InputStream从源设备输入到程序,通过OutputStream从程序输出到目标设备,从而实现数据的传输。IO流中的输入输出都是相对于程序而言的

    InputStream的常用方法

    public static read()
        从此字节流中读取一个数据字节
    
    public static read(byte[] b)
        从此输入流中将最多b.length个字节的数据读入一个byte数组中
    
    public static read(byte[] b,int off,int len)
        指定byte数组中从偏移量off开始的len个字节读出此文件流    
    
    os.close()
        关闭此文件输出流并释放与此流有关的所有系统资源

    OutputStream的常用方法

    public void write(int b)
        将指定字节写入此文件输出流
    
    public void write(byte[] b)
        将b.length个字节从指定byte数组写入到文件输出流中去
    
    public void write(byte[] b,int off,int len)
        指定byte数组中从偏移量off开始的len个字节写入此文件输出流        
    
    flush() 
        刷新缓存区并强制写出所有缓冲的输出字节    
    
    os.close()
        关闭此文件输入流并释放与此流有关的所有系统资源

    InputStream和OutputStream这两个类虽然提供了一系列的读写数据有关的方法,但是这两个类是抽象类,不能被实例化,因此,针对不同的功能,InputStream和OutputStream提供了两个不同的子类,这些子类形成了一个体系结构

    字节流读写文件

    由于计算机中的数据基本都保存在硬盘的文件中,因此操作文件中的数据时一种很常见的操作。在操作文件时,最常见的就是从文件中读取数据并将数据写入文件,即文件的读写。针对文件的读写,JDK专门提供了两个类,分别是FileInputStream和FileOutputStream。

    FileInputStream是InputStream的子类,它是操作文件的字节输入流,专门用于读取文件中的数据。由于从文件中读取数据时重复性的操作,因此需要通过循环语句来实现数据的持续读取。

    接下来通过一个案例来实现字节流对文件数据的读取:

    public class Example01 {
        public static void main(String[] args) throws Exception {
            //创镌一个文件字节输入流对象
            FileInputStream in = new FileInputStream("test.txt");
            int b=0;            //定义一个int类型的变量b,记住每次读取的一个字节
            while(true) {
                b=in.read();    //变量b记住读取的一个字节
                if(b==-1) {        //如果读取的字节为-1,跳出while循环
                    break;
                }
                System.out.println(b);    //否则将b输出
            }
        }
    }

    与FileInputStream对应的是FileOutputStream。FileOutputStream是OutputStream的子类,他是操作文件的字节输出流,专门把输入写入文件。

    接下来通过一个案例来演示如何将数据写入文件:

    public class Example02 {
        public static void main(String[] args) throws IOException {
            FileOutputStream out = new FileOutputStream("example.txt");
            String str="波音飞机";
            byte[] b = str.getBytes();
            for (int i = 0; i < b.length; i++) {
                out.write(b[i]);
            }
            out.close();
        }
    }

    需要注意的是,如果是通过FileOutputStream向一个已经存在的文件中写入数据,那么该文件中的数据首先会被情况,再写入数据。若希望在已存在的文件内容之后追加新内容,则可使用FileOutputStrem的构造函数FileOutputStream(String file, boolean append)来创建文件输出流对象,并把append参数的值设置为true。

    接下来通过一个案例来演示如何将数据追加到文件末尾

    public class Example01 {
        public static void main(String[] args) throws Exception {
            //创镌一个文件字节输入流对象
            FileInputStream in = new FileInputStream("test.txt");
            int b=0;            //定义一个int类型的变量b,记住每次读取的一个字节
            while(true) {
                b=in.read();    //变量b记住读取的一个字节
                if(b==-1) {        //如果读取的字节为-1,跳出while循环
                    break;
                }
                System.out.println(b);    //否则将b输出
            }
        }
    }

    由于IO流在进行数据读写操作时会出现异常,为了代码的简洁,在上面的程序中使用了throws关键字将异常抛出。然而一遇到IO异常,IO流的close()方法将无法得到执行,流对象所占用的系统资源将得不到释放,因此,为了保证IO流的close()方法必须执行,通常将关闭流的操作写在finally代码块中

    finally{
        try{
            if(in!=null){
                in.close;
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }

    文件的拷贝

    在应用程序中,IO流通常都是成对出现的,即输入流和输出流一起使用。例如文件的拷贝就需要通过输入流来读取文件中的数据,通过文件输出流写入文件。

    接下来通过一个案例来演示如何进行文件内容的拷贝:

    public class Example01 {
        public static void main(String[] args) throws Exception {
            //创建一个字节输入流,用于读取当前目录下sourse文件夹中的map3文件
            FileInputStream in = new FileInputStream("sourse\周深 - 大鱼.mp3");
            
            //创建一个字节输出流,用于把读取的字节写入到target目录下的文件中
            FileOutputStream out = new FileOutputStream("target\周深 - 大鱼.mp3");
    
            int len;    //定义一个整型类型的变量len,记住每次读取的一个字节
            long starttime = System.currentTimeMillis();         //获取拷贝文件前的系统时间
            while((len=in.read())!=-1) {
                out.write(len);      //将读到的字节写入文件
            }
            long endtime = System.currentTimeMillis();
            System.out.println("拷贝时间: "+(endtime-starttime)+"毫秒");
            in.close();
            out.close();
        }
    }

    字节流的缓冲区

    在拷贝文件时,可以一次性读取多个字节的数据,并保存在字节数组中,然后将字节而数组中的数据一次性写入文件。

    接下来通过修改文件来学习如何使用缓冲区拷贝文件

    public class Example02 {
        public static void main(String[] args) throws Exception {
            //创建一个文件输入流,用于读取当前目录下sourse目录下的mp3文件
            FileInputStream in = new FileInputStream("sourse\周深 - 大鱼.mp3");
            
            //创建一个文件输出流,用于将读取的数据写入当前目录下的target文件中
            FileOutputStream out = new FileOutputStream("target\周深 - 大鱼.mp3");
            
            //以下是用缓冲区读写文件
            byte[] buff = new byte[1024];    //定义一个字节数组,作为缓冲区
            
            int len;
            long startTime = System.currentTimeMillis();
            while((len=in.read(buff))!=-1) {    //判断是否读到文件末尾
                out.write(buff, 0, len);    //从第一个字节开始,想文件写入len个字符
            }
            long endTime = System.currentTimeMillis();
            System.out.println("拷贝文件所用的时间:"+(endTime-startTime));
            in.close();
            out.close();
        }
    }

    在拷贝过程中,使用while循环逐渐实现字节文件的拷贝,每循环一次,就从文件读取若干字节填充字节数组,并通过变量len记住读入数组的字节数,然后从数组的第一个字节开始,将len个字节一次写入文件。循环往复,当len值为-1时,说明已经读到了文件的末尾,循环会结束,整个拷贝过程也就结束了。
    程序中的缓冲区就是一块内存,该内存主要用于存放暂时输入输出的数据,由于使用缓冲区减少了对文件的操作次数,所有可以提高读写数据的效率。

    在IO包中提供两个带缓冲的字节流,分别是BufferedInputStream和BufferedOutputStream,它们的构造方法中分别接收InputStream和OutputStream类型的参数作为对象,在读写数据时提供缓冲功能。

    接下来通过一个案例来学习BufferedInputStream和BufferedOutputStream这两个流的用法:

    public class Example03 {
        public static void main(String[] args) throws Exception {
            //创建一个带缓冲区的输入流
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("src.txt"));
        
            //创建一个带缓冲区的输出流
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("des.txt"));
            int len;
            while((len=bis.read())!=-1){
                bos.write(len);
            }
            bis.close();
            bos.close();
        }
    }

    当调用了read()或者write()方法读写数据时,首先将读写的数据存入定义好了的字节数组,然后将字节数组一次性写入到文件中。从而提高了数据的读写效率

    学习中,博客都是自己学习用的笔记,持续更新改正。。。
  • 相关阅读:
    VS工作目录,输出目录
    Google的C++开源代码项
    C++文件读写
    深拷贝浅拷贝
    Efficient Graph-Based Image Segmentation
    Graph Cut 简介
    Graph Cut
    "GrabCut" - Interactive Foreground Extraction using Iter
    EM算法
    Python图像处理库(2)
  • 原文地址:https://www.cnblogs.com/Tunan-Ki/p/11668934.html
Copyright © 2011-2022 走看看