46-10-IO流-文件复制(重要)

102 阅读12分钟
IO流  I input   output  的概念 程序停止,内存中的数据变量/数组/集合消失	I input   output   
    	而IO流可以把数据写出到硬盘文件中,实现数据的持久化保存
 按照流的方向:
        输入流:   字节输入流: InputStream 字符输入流: Reader 
        输出流:  字节输出流: OutputStream   字符输出流: Writer
      计算机中的一切都是字节流,字符流: 只能用来处理纯文本文件 
            .java,.html,.xml,.css,.js,.dtd,.xsd 是纯文本文件
            .doc,.xls 不是纯文本文件 
   OutputStream类和InputStream类:抽象类,不能直接new对象          
 close(): 关闭流, write(int b): 写出一个字节 write(byte[] bs): 写出一个字节数组
 write(byte[] bs,int startIndex,int len): 写出一个字节数组的一部分
      参数:  byte[] bs: 字节数组  int startIndex: 起始索引   int len: 写出字节的个数
 OutputStream类不能直接new对象,
          其子类FileOutputStream  (File/String)  以文件字节输出流 File/String类型的文件路径
 String变成字节数组?  byte[] getBytes(): 获取调用方法字符串对应的字节数组
     字节输出流都在一行追加续写改变格式   
    FileOutputStream(File/String path,boolean append): 
    参数:    boolean append    true: 追加写入,继续写入  false: 覆盖/重写写入
                默认不写第二个参数,就是false,代表覆盖/重写写入 
       换行也是字符串:   windows: \r\n      linux/unix: \n             
 字节输出流写数据的方法
    	1.创建文件字节输出流FileOutputStream类的对象fos,绑定目标文件
    	2.文件字节输出流FileOutputStream类的对象fos调用write方法,写出字节到文件
    	3.字节输出流FileOutputStream类的对象fos调用close方法,关闭流释放资源
public class Demo03OputStream {
    public static void main(String[] args) throws IOException {
        //1.创建文件字节输出流FileOutputStream类的对象fos,绑定目标文件
        FileOutputStream fos = new FileOutputStream("day11_xw\\fos1.txt"); 
        //2.文件字节输出流FileOutputStream类的对象fos调用write方法,写出字节到文件
        //写出单个字节: write(int b)
        fos.write(97); 
        fos.write('A'); 
        //写出字节数组: write(byte[] bs)
        byte[] bs = {66,67,68,69,70,71};//B-G
        fos.write(bs); 
        //写出一个字节数组的一部分: write(byte[] bs,int startIndex,int len) 
        //把D,E,F 重新写一遍
        fos.write(bs,2,3); 
        //写出一个字符串
        byte[] bs2 = "好想有个女朋友".getBytes();
        fos.write(bs2); 
        fos.write("有个女同桌也行".getBytes()); 
        //3.字节输出流FileOutputStream类的对象fos调用close方法,关闭流释放资源
        fos.close();
    }
}
public class Demo04Append {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("day11_xw\\fos2.txt",true);
        fos.write("好好学习".getBytes());
        //写入换行
        fos.write("\r\n".getBytes());
        fos.write("天天向上".getBytes());
        fos.write("\r\n".getBytes());
        fos.close();
    }
}

InputStream类

 close() read(): 读取一个字节,返回int数据
     int read(byte[] bs): 读取一个字节数组,返回int数据(表示读取到的字节的数量)
        	参数: 	byte[] bs: 字节数组,作用是存储读取到的多个字节的内容
        	返回值: int: 表示读取到的字节的数量 
    	    如果read方法返回-1,说明文件读取结束了
    一次读取一个字节数组         
    String(byte[] bs): 把构造方法参数字节数组,转换成字符串
    String(byte[] bs,int startIndex,int len):   把构造方法参数字节数组从指定索引开始后面的len个字节,转换成字符串
  InputStream子类FileInputStream类  public FileInputStream(File/String类型的文件路径path) 
  一次读取一个字节
public class Demo03InputStream {
    public static void main(String[] args) throws IOException {
        //1.创建文件字节输入流FileInputStream类的对象fis,绑定源文件
        FileInputStream fis = new FileInputStream("day11_xw\\fis1.txt");

        //2.文件字节输入流FileInputStream类的对象fis调用read方法,从源文件中读取出字节内容
        //定义int变量,保存每次读取到的一个字节的内容
        int b = 0;

        //从fis对象关联的文件中,读取一个字节,返回int数字,赋值给变量b
        //最后判断b的值是否等于-1
        while ((b = fis.read()) != -1) {
            System.out.println(b+"<------>"+(char)b);
        } 
        //3.文件字节输入流FileInputStream类的对象fis调用close方法,关闭流释放资源
        fis.close(); 
    } 
}
 一次读取一个字节数组
 public class Demo04InputStream {
    public static void main(String[] args) throws IOException {
        //1.创建文件字节输入流FileInputStream类的对象fis,绑定源文件
        FileInputStream fis = new FileInputStream("day11_xw\\fis2.txt");

        //2.文件字节输入流FileInputStream类的对象fis调用read方法,从源文件中读取出字节内容
        //定义byte数组,用来保存每次读取到的多个字节的内容
        byte[] bs = new byte[2];

        //定义int变量,保存每次读取到的字节的个数
        int len = 0;

        //从fis对象关联的文件中,读取多个字节,存储到字节数组bs中,返回读取到的字节的个数,
        //赋值给int变量len,最后判断len的值是否等于-1
        while ((len = fis.read(bs)) != -1) {
            System.out.println(new String(bs,0,len));
        }
        //3.文件字节输入流FileInputStream类的对象fis调用close方法,关闭流释放资源
        fis.close();

    }
    

文件复制

使用字节流可以进行任何文件的复制,因为字节流操作的是组成文件的最小单元-字节
    字节流复制文件
    实现步骤:
        1.创建文件字节输入流FileInputStream类的对象fis,绑定源文件
        2.创建文件字节输出流FileOutputStream类的对象fos,绑定目标文件
        3.循环读(源文件)写(目标文件)
        4.关闭流,释放资源

    测试效率:  单字节循环复制文件: 30443 毫秒     字节数组循环复制:   55 毫秒
     
public class Demo04CopyFile {
    public static void main(String[] args) throws IOException {
        //1.记录开始时间
        long start = System.currentTimeMillis();
        //2.执行功能代码
        copy02();
        //3.记录结束时间
        long end = System.currentTimeMillis();

        //4.计算总耗时,并打印
        System.out.println("总耗时: "+(end - start)+" 毫秒");

    }
    //字节数组循环复制
    private static void copy02() throws IOException {
        //1.创建文件字节输入流FileInputStream类的对象fis,绑定源文件
        FileInputStream fis = new FileInputStream("day11_xw\\io\\from\\jzc.flv");

        //2.创建文件字节输出流FileOutputStream类的对象fos,绑定目标文件
        FileOutputStream fos = new FileOutputStream("day11_xw\\io\\to\\jzc.flv");

        //3.字节数组循环读(源文件)写(目标文件)

        //定义byte数组,保存每次读取到的多个字节的内容
        byte[] bs = new byte[1024*8];

        //定义int变量,保存每次读取到的字节的个数
        int len = 0;
        //从fis对象关联的文件中读取多个字节,把读取到的多个字节的内容,存储到字节数组bs中
        //返回读取的字节的个数,赋值给int变量len
        //最后判断len的值是否等于-1
        while ((len = fis.read(bs)) != -1) {
            //把字节数组bs中的内容,从索引0开始后面的len个字节,写出到fos对象关联的文件中
            fos.write(bs,0,len);
        }

        //4.关闭流,释放资源
        fis.close();
        fos.close();
    }

    //单字节循环复制文件
    private static void copy01() throws IOException {
        //1.创建文件字节输入流FileInputStream类的对象fis,绑定源文件
        FileInputStream fis = new FileInputStream("day11_xw\\io\\from\\jzc.flv");

        //2.创建文件字节输出流FileOutputStream类的对象fos,绑定目标文件
        FileOutputStream fos = new FileOutputStream("day11_xw\\io\\to\\jzc.flv");

        //3.单字节循环读(源文件)写(目标文件)

        //定义int变量,保存每次读取到的单个字节的内容
        int b = 0;

        //从fis对象关联的文件中读取一个字节,返回int数字,赋值给变量b
        //最后判断b的值是否等于-1
        while ((b = fis.read()) != -1) {
            //把b中的内容写出到fos对象关联的文件中
            fos.write(b);
        }

        //4.关闭流,释放资源
        fis.close();
        fos.close();
    }
}


IO流中的异常处理

 1.throws: 声明抛出异常
        2.try-catch: 捕获处理异常
            try{
                有可能产生异常的代码
            } catch(异常类 对象名){
                异常处理的代码
            } finally{
                释放资源的代码
            }  
 public class Demo05IOException {
    public static void main(String[] args) {
        //提升变量的作用域,进行初始化
        //不初始化的话,在创建对象时,如果出异常,变量没有值,不能调用方法
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("day11_xw\\io\\from\\jzc.flv");
            fos = new FileOutputStream("day11_xw\\io\\to\\jzc.flv");
            byte[] bs = new byte[1024*8];
            int len = 0;
            while ((len = fis.read(bs)) != -1) {
                fos.write(bs,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //必须分开处理
            //如果try中new对象出了异常,变量的初始值都是null
            //调用方法,报出空指针异常
            if(fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}           

缓冲流

字节输出缓冲流
BufferedOutputStream(OutputStream os)类: 字节缓冲输出流
BufferedInputStream类   字节输入缓冲流
public void write(byte[] bs,int index,int len): 写出一个字节数组的一部分
参数:   byte[] bs: 字节数组   int index: 起始索引  int len: 字节个数
    步骤
        1.创建OutputStream类的子类FileOutputStream的对象fos,绑定目标文件
        2.创建字节缓冲输出流BufferedOutputStream的对象bos,构造方法传递fos
        3.字节缓冲输出流BufferedOutputStream的对象bos调用write方法,写出字节
        4.字节缓冲输出流BufferedOutputStream的对象bos调用close方法,关闭流,释放资源

    注意:
        1.字节缓冲输出流使用缓冲流,千万不要调用flush方法了
        2.字节缓冲输出流不用自己关闭缓冲流所关联的其它流
### 字节输入缓冲流
		public BufferedInputStream(InputStream is):
			参数: InputStream is 字节输入流抽象类 传递子类FileInputStream对象

	使用步骤:
		1.创建InputStream类的子类FileInputStream对象fis,绑定源文件
		2.创建高效字节输入流BufferedInputStream对象bis,传递InputStream类的子类FileInputStream对象
		3.高效字节输入流BufferedInputStream对象bis调用read方法,读取字节
		4.关闭流
	字节输入缓冲流	 只需要关闭缓冲流,自动关闭缓冲流所关联的其它流对象 ,千万不要调用flush方法了
字节缓冲流复制文件代码实现
/*
    字节缓冲流复制文件 源文件: day12_sw\\copyfrom\cxyjzc.flv
    目标文件: day12_sw\\copyto\cxyjzc.flv
   步骤:
        1.创建字节缓冲输入流BufferedInputStream类的对象bis,绑定源文件
        2.创建字节缓冲输出流BufferedOutputStream类的对象bos,绑定目标文件
        3.单字节/字节数组循环读(源文件)写(目标文件)
        4.关闭流释放资源

    字节缓冲流复制文件效率对比:
        1.单字节循环复制: 311 毫秒
        2.字节数组循环复制: 23 毫秒
 */
public class Demo04BufferedCopyFile {
    public static void main(String[] args) throws IOException {
        //源文件: copyfrom\cxyjzc.flv
        File srcFile = new File("day12_sw\\copyfrom\\cxyjzc.flv");
        File destFile = new File("day12_sw\\copyto\\cxyjzc.flv");

        //记录开始时间
        long start = System.currentTimeMillis();
        //调用方法
        copy02(srcFile,destFile);
        //记录结束时间
        long end = System.currentTimeMillis();
        //打印总耗时
        System.out.println("总耗时: "+(end-start)+" 毫秒");
    }


    //定义方法,单字节循环复制文件
    public static void copy02(File srcFile,File destFile) throws IOException {
        //1.创建字节缓冲输入流BufferedInputStream类的对象bis,绑定源文件
        BufferedInputStream bis = 
            new BufferedInputStream(new FileInputStream(srcFile));

        //2.创建字节缓冲输出流BufferedOutputStream类的对象bos,绑定目标文件
        BufferedOutputStream bos = 
            new BufferedOutputStream(new FileOutputStream(destFile));

        //3.字节数组循环读(源文件)写(目标文件)

        //定义int变量,保存每次读取到的多个字节的个数
        int len = 0;
        //定义字节数组,保存每次读取到的多个字节的内容
        byte[] bs = new byte[1024];

        //从bis关联的文件中,读取一些字节,保存到字节数组bs中,返回读取到的字节的个数,赋值给变量len
        //最后判断len的值是否等于-1
        while ((len = bis.read(bs)) != -1) {
            //把字节数组bs中从索引0开始后面的len个字节,写出到bos关联的文件中
            bos.write(bs,0,len);
        }

        //4.关闭流释放资源
        bis.close();
        bos.close();
    }

    //定义方法,单字节循环复制文件
    public static void copy01(File srcFile,File destFile) throws IOException {
        //1.创建字节缓冲输入流BufferedInputStream类的对象bis,绑定源文件
        BufferedInputStream bis = 
            new BufferedInputStream(new FileInputStream(srcFile));

        //2.创建字节缓冲输出流BufferedOutputStream类的对象bos,绑定目标文件
        BufferedOutputStream bos = 
            new BufferedOutputStream(new FileOutputStream(destFile));

        //3.单字节循环读(源文件)写(目标文件)

        //定义int变量,保存每次读取到的单个字节的内容
        int b = 0;
        //从bis关联的文件中,读取一个字节,返回该字节对应的int数字,赋值给变量b
        //最后判断b的值是否等于-1
        while ((b = bis.read()) != -1) {
            //把b中的内容写出到bos关联的文件中
            bos.write(b);
        }

        //4.关闭流释放资源
        bis.close();
        bos.close();
    }
}

文件夹复制

package com.it.d2_copy_file;

import java.io.*;

/*
    定义方法复制文件夹
 */
public class Demo04CopyDir {
    public static void main(String[] args) throws IOException {
        //创建源文件夹
        File srcDir = new File("E:\\黑马JavaEE基础班156期-武汉");
        //创建目标文件夹
        File destDir = new File("C:\\Users\\smhjx\\Desktop\\aaaaa");

        //调用方法完成文件夹的复制
        copyDir2Dir(srcDir,destDir);
    }

    /**
     * 定义方法,完成文件夹的复制
     * @param srcDir:     被复制的文件夹(源文件夹)
     * @param destDir:    存储复制后文件夹的目录(目标文件夹)
     */
    public static void copyDir2Dir(File srcDir, File destDir) throws IOException {
        //创建新的目标文件夹(父路径: destDir,文件夹名字: srcDir文件夹的名字)
        File newDestDir = new File(destDir, srcDir.getName());
        //判断如果新的目标文件夹不存在,则创建
        if (!newDestDir.exists()) {
            newDestDir.mkdirs();
        }
        //获取源文件夹中所有的子文件夹/子文件组成的File对象数组
        File[] files = srcDir.listFiles();
        //安全判断
        if (files != null && files.length > 0) {
            //遍历
            for (File file : files) {
                //判断如果当前File对象是文件
                if (file.isFile()) {
                    //完成把当前文件file复制到目标文件夹newDestDir中
                    copyFile2Dir(file,newDestDir);
                } else {
                    //说明是文件夹,递归调用
                    copyDir2Dir(file,newDestDir);
                }
            }
        }
    }

    /**
     * 把文件复制到指定的文件夹
     * @param srcFile:    当前文件对应的File对象
     * @param destDir     存储目标文件的路径(目标文件夹)
     */
    private static void copyFile2Dir(File srcFile, File destDir) throws IOException {
        //在目标文件夹destDir下,创建一个和当前文件名称相同的文件
        File destFile = new File(destDir, srcFile.getName());
        //字节缓冲流完成文件的复制
        //创建文件字节输入缓冲流,绑定源文件
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
        //创建文件字节输出缓冲流,绑定目标文件
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));
        //字节数组循环读写
        byte[] bs = new byte[1024];
        int len;
        while ((len = bis.read(bs)) != -1) {
            bos.write(bs,0,len);
        }
        //关闭流释放资源
        bis.close();
        bos.close();
    }
}