java IO流

目录

一、IO流概述

 1.1 IO流概述 Input Output Stream

 1.2 IO流分类

 1.3 IO流体系结构

 1.4 File类的使用

二、文件流

2.1 文件字节流FileInputStream和FileOutputStream

2.2 文件字符流FileReader和FileWriter

三、缓冲流

3.1 缓冲字节流BufferedInputStream和BufferedOutputStream

3.2 缓冲字符流BufferedReader和BufferedWriter

四、数据流和对象流

4.1 数据流DataInputStream和DataOutputStream

4.2 对象流ObjectInputStream和ObjectOutputStream

4.3 序列化和反序列化

五、其他流

5.1 其他流

 5.2 复制文件夹


一、IO流概述

1.1 IO流概述 Input Output Stream

        在java程序中,对于数组的输入/输出操作以“流(stream)” 的方式进行;Java提供了各种各样的“流”类,用以获取不同种类的数据;程序中通过标准的方法输入或输出数据。java的流类型一般位于java.io包中。

        数据源data source,提供原始数据的原始媒介。常见的:数据库、文件、其他程序、内存、网络连接、IO设备。

        流是一个抽象、动态的概念,是一连串连续动态的数据集合。

        数据源就像水箱,流就像水管中流着的水流,程序就是我们最终的用户。流是一个抽象动态的概念,是一连串连续动态的数据集合。

 1.2 IO流分类

按流的方向分类:

        输入流:数据流向是数据源到程序(以InputStream、Reader结尾的流)。

        输出流:数据流向是程序到目的地(以OutputStream、Writer结尾的流)。

 注意:

        输入/输出流的划分是相对程序而言的,而不是相对数据源。

 按处理的数据单元分类:

  1. 字节流:以字节为单位获取数据,命名上以Stream结尾的流一般是字节流,顶级类InputStream、OutputStream。
  2. 字符流:以字符为单位获取数据,命名上以Reader/Writer结尾的流一般是字符流,顶级类Reader、Writer。

按处理对象不同分类:

节点流:可以直接从数据源或目的地读写数据,如 FileInputSteam、FileReader等。

处理流:不直接连接到数据源或目的地,是“处理流的流”。通过对其他流的处理提高程序的性能,如BufferedInputStream、BufferedReader等。处理流也叫包装流。

节点流处于IO操作的第一线,所有操作必须通过它们进行;处理流可以对节点流进行包装,提高性能或提高程序的灵活性。

生活案例:节点流就好比水井、水库,处理流就好比自来水厂、水塔等,目的是为了过滤和方便。但是如果没有水井、水库,只有自来水厂和水塔肯定不行。

 1.3 IO流体系结构

字节流

  • InputStream和OutputStream是java语言中最基本的两个字节输入输出流。其他所有字节输入输出流类都继承自这两个基类。
  • 这两个类都是抽象类,不能创建他们的实例,只能使用他们的子类
  • FilterInputStream和FilterOutputStream是所有包装流的父类

Reader和Writer

  • Java语言中两个最基本的两个字符输入输出类。
  • 其他所有的字符输入输出流类都继承自这两个基类。
  • 这两个类都是抽象类,不能创建他们的实例,只能使用他们的子类

 

 1.4 File类的使用

File类代表文件和文件夹。主要作用有两个:获取文件或者文件夹的属性;实现对文件、文件夹的创建和删除。文件夹:file folder    目录directory

【示例1】使用File获取文件或文件夹属性

public class TestFile1 {
    public static void main(String[] args) {
        //1.创建一个File对象,指向一个文件或者文件夹
        //File file = new File("c:\\bjsxt\\readme.txt");
        //File file = new File("c:/bjsxt/readme.txt");
        //File file = new File("readme.txt");
        File file = new File("c:/");
        //2.使用这个File对象,获取文件或者文件夹的属性
        System.out.println(file.getName());//文件或者文件夹的名称
        System.out.println(file.length());//长度
        System.out.println(file.exists());//是否存在
        System.out.println(file.getPath());//
        System.out.println(file.getAbsolutePath());//绝对路径
        System.out.println(file.isDirectory());//判断file是否指向一个目录
        System.out.println(file.isFile());//判断file是否指向一个文件

        System.out.println(file.isHidden());
        System.out.println(file.canWrite());
        System.out.println(file.canRead());
        System.out.println(file.canExecute());

       //String [] fileNameArr =  file.list();
        //某个文件夹下有哪些子文件夹和文件
        System.out.println("============");
       File fileArr[] =  file.listFiles();
       for(File f :fileArr){
           //System.out.println(f.toString());
          System.out.print(new Date(f.lastModified()).toLocaleString());
           if(f.isFile()){
               System.out.print("      "+f.length()+" ");
           }else{
               System.out.print("  <DIR>           ");
           }
           System.out.println(f.getName());
       }
    }
}

【示例2】使用File类新建、删除文件和文件夹

public class TestFile2 {
    public static void main(String[] args) {
        //创建一个File对象
        //File file = new File("c:/bjsxt/readme.txt");
        File file = new File("c:/bjsxt/abc/cba/acb/bac/readme.txt");
        //如果文件存在就删除,如果不存在就创建
        if(file.exists()){
            file.delete();
        }else{
            try {
                //判断所在文件夹是否存在,不存在,要先创建文件夹
                File dir = file.getParentFile();
                if(!dir.exists()){
                    //dir.mkdir();//make directory
                    dir.mkdirs();
                }
                //创建文件
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

注意:

        File不仅可以指向一个文件,也可以指向一个文件夹(作为一个文件对待)

        File不能对文件的内容进行操作,需要借助IO流实现

二、文件流

2.1 文件字节流FileInputStream和FileOutputStream

  • FileInputStream和FileOutputStream是字节流,是节点流,是数据源,目的地和文件。
  • 复制文件需要分别创建一个输入流和输出流完成文件读写
  • 需要创建一个中转站,借助循环和中转站完成复制。
  • 流使用完一定要关闭,这和垃圾回收没有关系

【示例3】复制文件(中转站是一个字节)

public class TestFileStream {
    public static void main(String[] args) throws IOException {
        //1.创建流
        File file1 = new File("e:/readme.txt");
        File file2 = new File("e:/readme2.txt");
        InputStream fis = new FileInputStream(file1);
        OutputStream fos = new FileOutputStream(file2);
        //2.使用流
        //2.1 准备一个中转站(一个字节)
        int n;
        //2.2 读取一个字节到中转站
        n = fis.read();
        while(n!=-1){//读到了文件的末尾
            //2.3 写一个字节到目的文件
            fos.write(n);
            //2.4 再读一个
            n = fis.read();
        }
        //3.关闭流
        fis.close();
        fos.close();
    }
}

缺点:中转站太小,速度慢,效率低;复制更大的文件效果更明显;可以将中转站由一个字节变为一个字节数组,减少读写硬盘的次数。

问题:如何不是覆盖文件,而是追加内容,如何实现。

【示例4】复制文件(中转站是一个字节数组)

public class TestFileStream2 {
    public static void main(String[] args) throws IOException {
        //1.创建流
//        File file1 = new File("e:/readme.txt");
//        File file2 = new File("e:/readme2.txt");
//        InputStream fis = new FileInputStream(file1);
//        //OutputStream fos = new FileOutputStream(file2);//默认是覆盖文件
//        OutputStream fos = new FileOutputStream(file2,true);//这是追加内容
//        InputStream fis = new FileInputStream(new File("e:/readme.txt"));
//        OutputStream fos = new FileOutputStream(new File("e:/readme2.txt"),true);
        InputStream fis = new FileInputStream("e:/readme.txt");
        OutputStream fos = new FileOutputStream("e:/readme2.txt",true);
        //2.使用流
        //2.1 准备一个中转站(一个字节数组)
        byte [] buf = new byte[1024];
        //2.2 读取一些字节到中转站
        int len = fis.read(buf);//读取文件的数据到buf数组,返回真实读取的字节个数赋给len
        while(len!=-1){//读到了文件的末尾
            //2.3 写一个字节字节数组到目的文件
            //fos.write(buf);
            fos.write(buf,0,len);
            //2.4 再读一些字节到字节数组
            len = fis.read(buf);
        }
        //3.关闭流
        fis.close();
        fos.close();
    }
}

【示例5】进行异常处理

public class TestFileStream3 {
    public static void main(String[] args) {
        InputStream fis = null;
        OutputStream fos = null;
        try{
            //1.创建流
            fis = new FileInputStream("e:/readme.txt");
            fos = new FileOutputStream("e:/readme2.txt");
            //2.使用流
            //2.1 准备一个中转站(一个字节数组)
            byte [] buf = new byte[1024];
            //2.2 读取一些字节到中转站
            int len = fis.read(buf);
            while(len!=-1){//读到了文件的末尾
                //2.3 写一个字节字节数组到目的文件
                //fos.write(buf);
                fos.write(buf,0,len);
                //2.4 再读一些字节到字节数组
                len = fis.read(buf);
            }
        }catch (FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //3.关闭流
            try {
                if(fis!= null){
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(fos!= null){
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 异常处理的分析:创建流、使用流要使用一次try-catch语句,关闭流要分开进行异常处理
  • Java7异常处理新特征:try-with-resources:不用显示的进行资源的关闭,只要将资源的实例化对象放入try后面的()中,作用范围是当前try语句,执行完毕(正常完成或是发生意外)后就会自动进行关闭,可省略finally语句,更加简单实用。

【示例6】JDK7异常处理新特征

public class TestFileStream4 {
    public static void main(String[] args) {
        try(InputStream  fis = new FileInputStream("e:/readme.txt");
            OutputStream fos = new FileOutputStream("e:/readme2.txt")){
            //1.创建流
            //2.使用流
            //2.1 准备一个中转站(一个字节数组)
            byte [] buf = new byte[1024];
            //2.2 读取一些字节到中转站
            int len = fis.read(buf);
            while(len!=-1){//读到了文件的末尾
                //2.3 写一个字节字节数组到目的文件
                //fos.write(buf);
                fos.write(buf,0,len);
                //2.4 再读一些字节到字节数组
                len = fis.read(buf);
            }
        }catch (FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 关于Java9中异常处理的新变化:try 之前定义好对象,try () 括号中引入创建好的对象。如果多个对象,使用;分隔。如果try之前定义的对象会抛出异常,就不推荐使用该方式,因为需要在方法签名中throws异常。

【示例7】JDK9异常处理新特征

public class TestFileStream5 {
    public static void main(String[] args) throws IOException {
        //1.创建流
        InputStream fis = new FileInputStream("e:/readme.txt");;
        OutputStream fos =  new FileOutputStream("e:/readme2.txt");
        try(fis;fos){
            //2.使用流
            //2.1 准备一个中转站(一个字节数组)
            byte [] buf = new byte[1024];
            //2.2 读取一些字节到中转站
            int len = fis.read(buf);
            while(len!=-1){//读到了文件的末尾
                //2.3 写一个字节字节数组到目的文件
                //fos.write(buf);
                fos.write(buf,0,len);
                //2.4 再读一些字节到字节数组
                len = fis.read(buf);
            }
        }catch (FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.2 文件字符流FileReader和FileWriter

FileReader和FileWriter是字符流,节点流,数据源和目的地是文件。

【示例8】复制文件(中转站是一个字符)

public class TestFileReaderWriter {
    public static void main(String[] args) throws IOException {
        //1.创建字符流
        Reader fr = new FileReader(new File("e:/readme.txt"));
        Writer fw = new FileWriter("e:/readme2.txt");
        //2.使用字符流
        /*
        int n = fr.read();//一次读一个字符,不是一个字节。一个汉字一次搞定
        while(n!= -1){
            //System.out.println((char)n);
            fw.write(n);
            n = fr.read();
        }
        */
        int n=0;
        while((n = fr.read())!=-1){
            fw.write(n);
        }        
        //3.关闭字符流
        fr.close();
        fw.close();
    }
}

【示例9】复制文件(中转站是一个字符数组,并进行异常处理)

public class TestFileReaderWriter2 {
    public static void main(String[] args) {
        //1.创建字符流
        try( Reader fr = new FileReader(new File("e:/readme.txt"));
             Writer fw = new FileWriter("e:/readm22.txt");){
            //2.使用字符流
            char 
            int len = fr.read(cbuf);
            while(len!= -1){
                //System.out.println(cbuf);
                fw.write(cbuf,0,len);
                len = fr.read(cbuf);
            }
        }catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

其实只有字节流,没有字符流,字符流的底层还是字节流,进行了封装转换,是开发者可以更简单的来处理非英文字符

字节流可以完成所有类型文件的复制(文本、音频、视频、图片、chm);字符流只可以完成文本文件的复制(txt、java)   doc不是文本文件;字符流一般用来处理包含中文的文本文件。

三、缓冲流

3.1 缓冲字节流BufferedInputStream和BufferedOutputStream

【示例10】复制文件(使用缓冲流字节流提高效率)

public class TestCopy5 {
    public static void main(String[] args) throws IOException {
        //1.创建一个输入流和输出流
      InputStream fis = new FileInputStream(new File("e:/JDK_API.CHM"));
      OutputStream fos = new FileOutputStream(new File("e:/JDK_API2.CHM"));
//默认输入缓冲区大小8192
      BufferedInputStream bis = new BufferedInputStream(fis); 
//默认输出缓冲区大小8192
      BufferedOutputStream bos = new BufferedOutputStream(fos);       
        //2.使用输入流和输出流完成文件复制
        //2.1准备一个中转站(水杯)
        int n;
        //2.2先读一个字节
        n = bis.read();//读取一个字节,赋给n
        while(n != -1){
            //2.3再写一个字节
            bos.write(n);
            //2.4在读一个字节
            n = bis.read();
        }
        //3.关闭输入流和输出流
        bis.close();
        bos.close();
    }
}

缓冲流的原理

只要关闭高层流即可,底层流不用手动关闭;因为高层的关闭方法就是把底层流关闭

如何刷新输出缓冲区(让缓冲区内容写入硬盘,保证一致)

  •         满了就自动刷新
  •         bos.close()先flush,再关闭
  •         手动刷新flush()

3.2 缓冲字符流BufferedReader和BufferedWriter

问题:之前的文件读写都是按照字节、字符或者数组来实现的,对于文本文件而言,能否按照行,一行行读写呢?

提供了BufferedReader和BufferedWriter实现按行读写

【示例11】复制文件(按行读写)

public class TestCopy6 {
    public static void main(String[] args) throws IOException {
         //创建两个流
        BufferedReader br = 
       new BufferedReader(new FileReader(new File("e:/sqlnet.log")));
        BufferedWriter bw = 
                new BufferedWriter(new FileWriter("e:/sqlnet2.log"));        
        //使用两个流完成按行读取的功能
        //中转站就是一个字符串,存储一行数据
        //先读一行
        String str =  br.readLine();
        while(str != null ){
            //再写一行
            bw.write(str);
            bw.newLine(); //bw.write("\r\n");不同操作系统中换行符是不同的
            //再读一行
            str = br.readLine();//!!!
        }
        //关闭两个流
        br.close();
        bw.close();
    }
}

总结1:BufferedReader和BufferedWriter的优点

1.速度快

2.简化编程

总结2:readLine()底层原理

底层还是一个一个字符的读取,append()放入到StringBuilder(或者char[])中,遇到换行符,将StringBuider(char[]) 转换成String并返回

总结3:不同的操作系统中换行符是不同的

Unix系统里,每行结尾只有“<换行>”,即“\n”;

Windows系统里面,每行结尾是“<回车><换行>”,即“\r\n”;

Mac系统里,每行结尾是“<回车>”,即“\r”。

四、数据流和对象流

4.1 数据流DataInputStream和DataOutputStream

之前使用文件流、缓冲流读取文件只能按照字节、数组方式读取,最方便的也是按行读取,能否很方便的实现对各种基本类型和引用数据类型的读写,并保留其本身的类型。数据流DataInputStream和DataOutputStream和对象流ObjectInputStream和ObjectOutputStream可以解决这个问题,最大的优势就是提供了方便操作各种数据类型的方法,直接调用,简单方便。

注意:

  •         只有字节流,没有字符流
  •         都是处理流,不是节点流
  •         数据流只能操作基本数据类型和字符串,对象流还可以操作对象
  •         写入的是二进制数据,无法直接通过记事本等查看
  •         写入的数据需要使用对应的输入流来读取

【示例12】使用数据流读写文件

public class TestDataStream {
    public static void main(String[] args) throws Exception {
        //write();
        read();
    }    
    public static void write() throws Exception{
        //创建输出流
       OutputStream fos = new FileOutputStream("e:/readme2.txt");
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        DataOutputStream dos = new DataOutputStream(bos);        
        //使用输出流
        dos.writeInt(123);
        dos.writeDouble(3.14);
        dos.writeChar('A');
        dos.writeBoolean(true);
        dos.writeUTF("bjsxt");        
        //关闭输出流
        dos.close();
    }    
    public static void read() throws Exception{
        //创建输入流
        DataInputStream dis = 
                new DataInputStream(new BufferedInputStream(
                        new FileInputStream(
                                new File("e:/readme2.txt"))));        
        //使用输入流
        System.out.println(dis.readInt());
        double d = dis.readDouble();
        System.out.println(d);
        System.out.println(dis.readChar());
        System.out.println(dis.readBoolean());
        System.out.println(dis.readUTF());
        //System.out.println(dis.readUTF());        
        //关闭输入流
        dis.close();
    }
}

 4.2 对象流ObjectInputStream和ObjectOutputStream

【示例13】使用对象流读写文件  

public class TestObjectStream {
    public static void main(String[] args) throws Exception {
        //write();
        read();
    }    
    public static void write() throws Exception{
        //创建输出流
        OutputStream fos = new FileOutputStream("e:/readme2.txt");
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        ObjectOutputStream oos = new ObjectOutputStream(bos);        
        //使用输出流
        oos.writeInt(123);
        oos.writeDouble(3.14);
        oos.writeChar('A');
        oos.writeBoolean(true);
        oos.writeUTF("bjsxt");
        oos.writeObject(new Date());
        oos.writeObject(new Student(1, "111", 22, 333.3));        
        //关闭输出流
        oos.close();
    }   
    public static void read() throws Exception{
        //创建输入流
        ObjectInputStream ois = 
                new ObjectInputStream(new BufferedInputStream(
                        new FileInputStream(
                                new File("e:/readme2.txt"))));        
        //使用输入流
        System.out.println(ois.readInt());
        double d = ois.readDouble();
        System.out.println(d);
        System.out.println(ois.readChar());
        System.out.println(ois.readBoolean());
        System.out.println(ois.readUTF());
        //System.out.println(dis.readUTF());
        Object date = (Date)ois.readObject();
        System.out.println(date);
        System.out.println(ois.readObject());        
        //关闭输入流
        ois.close();
    }
}

注意:使用对象流读写引用类型的数据,需要相应类实现Serializable接口,否则会提示异常,提示没有序列化,比如:java.io.NotSerializableException: com.bjsxt.entity.Student

4.3 序列化和反序列化

1. 什么是序列化和反序列化

序列化:Serialization 将对象的状态信息转换为可以存储或传输的形式的过程。

对象(内存)-------->字节数组  字节序列(外存、网络)

内存-----》硬盘       序列化

硬盘-----》内存       反序列化

反序列化:DeSerialization

字节数组   字节序列(外存、网络)----------------->对象

2.什么时候需要序列化和反序列化

存储和传输 比如存储到外存(硬盘)中   传输到网络

3.如何实现序列化和反序列化

相应的类要实现Serializable接口

public class Student implements Serializable {
}

ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(new Student(1, "111", 22, 333.3));
ObjectInputStream ois = new ObjectInputStream(bis);
Student stu = (Student)ois.readObject();

4.序列化的细节

  • 为什么序列化接口没有任何方法,那还有什么用
  • (查看ObjectOutputStream源码)
  • static属性不参与序列化
  • 如果不希望某个属性参与序列化,要使用transient修饰
  • Exception in thread "main" java.io.InvalidClassException:
  • com.bjsxt.entity.Student; local class incompatible:
  • stream classdesc serialVersionUID = 5954363181006202290,
  • local class serialVersionUID = -1877375566195009060  
  • 解决方案:给出一个固定的序列化版本号
  • 使用对象流把一个对象写到文件时不仅保证该对象是序列化的,而且该对象的成员对象也必须是可序列化的。
  • https://jingyan.baidu.com/article/656db918c36534e381249c83.html

五、其他流

5.1 其他流

1. 打印流:PrintStream 和PrintWriter

只有输出流, 没有输入流

System.out、System.err是PrintStream的实例变量

2.转换流:InputStreamReader和OutputStreamWriter

实现字节流到字符流的转换,是适配器设计模式的应用

只能从字节流转换成字符流,可以带来处理字符的便利。没有字符流转换成字节流的转换流,因为没有这种需求。

3.字节数组流ByteArrayInputStream和ByteArrayOutputStream

是节点流,数据源是字节数组,可以实现各种基本和引用数据类型与字节数组之间的相互转换

4.Java IO流的设计使用了装饰模式,动态组装流,可以减少子类的数量,是继承的一种替代方案

OutputStream fos = new FileOutputStream("e:/readme.txt");
//提高速度
BufferedOutputStream bos = new BufferedOutputStream(fos); 
//简化操作
DataOutputStream dos = new DataOutputStream(bos); 

【示例14】认识其他IO流

public class Test {
    public static void main(String[] args) throws IOException {
        //1.打印流  只有输出流,没有输入流
        PrintStream ps; //字节流  System.out System.err
        PrintWriter pw; //字符流  后面讲解Servlet时会使用
        //System.out就是PrintStream的一个引用变量    
        System.out.println();
        //System.err也是PrintStream的一个引用变量
        System.err.println();
        //println()强大作用:不管什么类型数据,都给你变成字符串,并输出
        //2.转换流
        //接收键盘的输入一行数据,并输出
        //接收一行数据,需要使用BufferedReader(或者Scanner)。接收键盘的输入,
 //需要使用System.in;@2
//        InputStream is = System.in; //三相插头
//将字节输入流InputStream转换为字符输入流Reader  三相转两相的转换头
//        Reader reader = new InputStreamReader(is);
//        BufferedReader br = new BufferedReader(reader);//两相的插座
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new FileWriter("e:/bjsxt.txt"));
        //使用两个流完成按行读取的功能
        //中转站就是一个字符串,存储一行数据
        //先读一行
       String str = br.readLine();
        while(!"bye".equals(str) ){
            //再写一行
            bw.write(str);
            //bw.write("\r\n");不同操作系统中换行符是不同的
            bw.newLine();
            //再读一行
            str = br.readLine();//!!!
        }
        //关闭两个流
        br.close();
        bw.close();
        FileInputStream fis; //节点流  数据源是文件
        FileOutputStream fos;//节点流  目的地是文件
        //数组流 节点流  数据源和目的地都是数组
        ByteArrayInputStream  bais;
        ByteArrayOutputStream baos;
    }
}

 5.2 复制文件夹

问题1:使用字节流还是字符流

        使用字节流 可能有图片、视频、音频......等二进制文件

问题2:如何提高复制速度

        BufferedInputStream和BufferedOutputStream

        byte [] buf = new byte[1024];

问题3:涉及的技能点

        1. IO流:文件的复制

        2. 递归:各级文件夹和文件的递归复制

        3. File类:文件夹的定义和创建

问题4:问题的迭代

        1.复制一个文件

        2.复制一个文件夹下所有的文件(不包括子文件夹)

        3.复制一个文件夹下所有的文件和子文件夹,从而完成文件夹的复制 

【示例15】复制一个文件

public class TestDirCopy {
    public static void main(String[] args) {
        copyFile("e:/readme.txt","d:/readme2.txt");
    }
    public static void copyFile(String sourceFileName,String targetFileName) {
        //1.创建一个输入流和输出流
        BufferedInputStream bis =  null;
        BufferedOutputStream bos = null;
        try {
            bis = new BufferedInputStream(new FileInputStream(new File(sourceFileName)));
            bos = new BufferedOutputStream(new FileOutputStream(targetFileName));
            //2.使用输入流和输出流完成文件复制
            //2.1准备一个中转站(水杯)
            byte [] buf = new byte[1024];
            int len = bis.read(buf);
            while(len !=-1){
                bos.write(buf, 0, len);
                len = bis.read(buf);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            //3.关闭输入流和输出流
            try {
                if(bis != null){
                    bis.close();
                }           
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(bos != null){
                    bos.close();
                }           
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

【示例16】复制一个文件文件夹(含子文件夹)

public class TestDirCopy3 {
    public static void main(String[] args) {
        //copyFile("e:/readme.txt","d:/readme2.txt");
        copyDir("e:/402视频","e:/zzz视频");
    }
    public static void copyDir(String sourceDirName,String targetDirName){
        //创建一个目的文件夹
        //File dir = new File("e:/403");
        File targetDir = new File(targetDirName);
        if(!targetDir.exists()){
            targetDir.mkdir();
        }        
        //复制源文件夹下的所有文件到目的文件夹
        File sourceDir = new File(sourceDirName);
        File [] files = sourceDir.listFiles();//文件夹下所有的文件和子文件夹
        for(File file:files){
            //如果是文件就复制
            if(file.isFile()){
        //copyFile("e:/402/402授课笔记.nyf","e:/zzz/402授课笔记.nyf");
         copyFile(sourceDirName+"/"+file.getName(),targetDirName+"/"+file.getName());
            }
            //如果是文件夹,就递归
            if(file.isDirectory()){
        //copyDir("e:/402/20180226-常用类","e:/zzz/20180226-常用类");
                copyDir(sourceDirName+"/"+file.getName(),targetDirName+"/"+file.getName());
            }
        }
    }    
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值