10.输入输出 10.1 File(目录和文件路径名的抽象表达形式) 10.2 字符流 10.3 字节流 10.4 缓冲流 10.5 编码 10.6 文档复制粘贴 10.7 集合和文件之间的转换 10.8 打印流 10.9 可变参数 10.10 数组转变为List集合 10.11 Properties 10.12 序列化流&&反序列化流

文件和目录路径名的抽象表示形式。

用户界面和操作系统使用与系统相关的路径名字符串 来命名文件和目录。此类呈现分层路径名的一个抽象的、与系统无关的视图。抽象路径名 有两个组件:

  1. 一个可选的与系统有关的前缀 字符串,比如盘符,"/" 表示 UNIX 中的根目录,"\\" 表示 Microsoft Windows UNC 路径名。
  2. 零个或更多字符串名称 的序列。

抽象路径名中的第一个名称是目录名,对于 Microsoft Windows UNC 路径名则是主机名。抽象路径名中第一个名称之后的每个名称表示一个目录;最后一个名称既可以表示目录,也可以表示文件。 抽象路径名没有前缀和名称序列。 

FIle类中常见方法使用:

package file;

import java.io.File;
import java.io.IOException;
import java.util.Date;

/*
 * File: 代表的是 文件与文件夹
 * 
 * 构造函数:
 *         public File(String pathname) : 根据路径名称创建一个File对象
 *         public File(String parent, String child) : 根据给定的父路径 与 给定的子路径或者文件, 创建一个File对象
 *         public File(File parent, String child) 根据给定的父File对象 与 给定的子路径或者文件, 创建一个File对象
 */
public class FileDemo {

    public static void main(String[] args) throws IOException {
//        testConstructor();
//        filePractice();
//        testFileDelete();
//        testMethod();
//        testRenameTo();
//        testFileMethod();
        testFileFunction();

    }
    //构造函数练习,注意构造函数只会产生一个file对象,不会产生文件
    public static void testConstructor(){
        //根据路径名称创建一个File对象,只是对路径下内容进行封装成对象,并没有对内容进行操作,不会产生文件
        File file = new File("F:\IO\a.txt");
        //根据给定的父路径 与 给定的子路径或者文件, 创建一个File对象
        File file1 = new File("F:\IO", "b.txt");
        //根据给定的父File对象 与 给定的子路径或者文件, 创建一个File对象
        File f = new File("F:\IO");
        File file2 = new File(f, "c.txt");
    }
    /*
     * File类中创建功能
     * 
     *         创建文件
     *             public boolean createNewFile() 
     *             如果返回值为true,原先文件不存在,创建文件
     *             如果返回值为false,原先文件存在, 不创建文件
     *         创建文件夹
     *             public boolean mkdir()
     *             public boolean mkdirs()
     * 
     * 
     *     绝对目录: 就是路径带盘符
     *     相对目录:就是路径不带盘符,  这个相对目录的起始位置是当前项目的根目录
     * 
     *  骑白马的不一定是王子, 也可能是唐僧
     *  创建了File对象后, 具体创建文件还是文件夹由调用的方法来决定的
     *  
     */
    public static void filePractice() throws IOException{
        File file = new File("F:\IO\a.txt");
        boolean b = file.createNewFile();//产生一个新文件,a.txt
        System.out.println("原目录了中不存在文件返回true,产生一个新文件:"+b);
        File file1 = new File("F:\IO\a.txt");
        boolean b1 = file1.createNewFile();
        System.out.println("原目录中存在文件返回false,不创建文件:"+b1);
        //创建文件夹
        File f1 = new File("F:\IO\aa");
        boolean m1 = f1.mkdir();
        System.out.println("原目录了中不存在文件夹返回true,产生一个新文件:"+m1);
        File f2 = new File("F:\IO\aa");
        boolean m2 = f2.mkdir();
        System.out.println("原目录了中不存在文件夹返回true,产生一个新文件:"+m2);
        //多层文件夹的创建
        //File ff = new File(F:\IO\aa\bb);
        File ff = new File("F:\IO\aa");
        File fff = new File("F:\IO\aa\bb");
        ff.mkdir();
        fff.mkdir();
        //上面我们看到了多层文件夹的创建,那么是不是有些麻烦呢,在这里我们引入另一种创建方法,
        File fff1 = new File("F:\IO\aa\bb");
        fff1.mkdirs();//此时发现呈现了同样的效果
        File fi = new File("F:\IO\a.txt");
        boolean flag = fi.mkdir();
        //我们发现创建成功了,只是文件夹的名称是问价名称
        System.out.println("调用创建文件夹的方法创建文件:"+flag);
    }
    /*
     * File类的删除功能:
     *         public boolean delete() : 可以删除文件 或 删除空文件夹
     *         通过java程序删除的文件 不经过回收站
     */
    public static void testFileDelete() throws IOException{
        File file1 = new File("F:\IO\a.txt");
        boolean flag = file1.createNewFile();
        System.out.println("创建文件成功:"+flag);
        boolean flag1 = file1.delete();
        System.out.println("删除文件是否成功:"+flag1);
        //删除文件夹,删除空文件夹,文件夹中如果存在东西,不能直接删除
        File file2 = new File("F:\IO\a.txt");
        boolean flag2 = file2.mkdir();
        System.out.println("创建文件成功:"+flag2);
        boolean flag3 = file2.delete();
        System.out.println("删除文件是否成功:"+flag3);
        //多层文件夹的删除
        File fff1 = new File("F:\IO\aa\bb");
        boolean boo = fff1.mkdirs();
        System.out.println("多层文件夹创建成功:"+boo);
        boolean boo1 = fff1.delete();
        //我们发现删除多层文件夹时,只能删除最底层的文件夹
        System.out.println("多层文件夹删除成功:"+boo1);
    }
    /*
     * File类中的判断功能:
     *         判断指定的File是否存在 
     *             public boolean exists()
     *         判断File是否是文件
     *             public boolean isFile()
     *         判断File是否是文件夹
     *             public boolean isDirectory()
     *         判断File是否可读
     *             public boolean canRead()
     *         判断File是否可写
     *             public boolean canWrite()
     *         判断File是否隐藏
     *             public boolean isHidden()
     *  boolean isAbsolute() 
          测试此抽象路径名是否为绝对路径名。 
     */
    public static void testMethod() throws IOException{
        File file = new File("F:\IO");
        System.out.println("判断指定的file是否存在:"+file.exists());
        System.out.println("判断指定的file是否是文件夹:"+file.isDirectory());
        System.out.println("判断指定的file是否是文件:"+file.isFile());
        System.out.println("判断是否可读:"+file.canRead());
        System.out.println("判断是否可写:"+file.canWrite());
        System.out.println("判断是否可隐藏:"+file.isHidden());
        System.out.println("判断此抽象路径是否为绝对路径名:"+file.isAbsolute());
        File file2 = new File("F:\IO\a.txt");
        file2.createNewFile();
        System.out.println("判断指定文件是否为文件:"+file2.isFile());
    }
    /*
     * File类中重命名功能:
     *         public boolean renameTo(File dest)
     *         如果两个File在同一文件夹下, 重命名功能
     *         如果两个File不再同一个文件夹下, 剪切功能并且重命名
     * 如果文件夹中已经存在此文件名文件,那么改名不成功,
     */
    public static void testRenameTo(){
        File file = new File("F:\IO\a.txt");
        File fi = new File("b.txt");
        File fil = new File("F:\IO\b.txt");
        boolean b = file.renameTo(fi);
        boolean bb = file.renameTo(fil);
        System.out.println("改文件名字,不在同一文件夹,剪切重命名:"+b);
        System.out.println("改文件名字,在同一文件夹,重命名:"+bb);
    }
    /*
     * File类中获取功能的基本方法:
     *         获取文件的绝对目录:  
     *             public String getAbsolutePath()
     *         获取文件的相对目录:
     *             public String getPath()
     *         获取文件的名字:
     *             public String getName()
     *         获取文件的大小:
     *             public long length()
     *         获取文件的最后修改时间:         
     *             public long lastModified()
     * getParent() 
          返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null。
     */
    public static void testFileMethod() throws IOException{
        File file = new File("F:\IO\aa.txt");
        file.createNewFile();
        System.out.println("获取文件的绝对路径:"+file.getAbsoluteFile());
        System.out.println("获取文件的相对目录:"+file.getPath());
        System.out.println("获取此抽象路径父目录的路径名字字符串,如果此路径没有指定父目录,则返回null:"+file.getParent());
        System.out.println("获取文件的名字:"+file.getName());
        System.out.println("获取文件的大小:"+file.length());
        System.out.println("获取文件的最后修改时间:"+file.lastModified());
        Date date = new Date(1495566380509L);
        System.out.println(date);
    }
    /*
     * File类中获取功能的高级方法
     *         返回指定目录下的文件与文件夹
     *             public String[] list()  结果不带盘符, 返回的数据是String类型
     *             public File[] listFiles() 结果带盘符, 返回的数据是File类型
     *         列出当前电脑上所有盘符
     *         public static File[] listRoots()
     * 
     */
    public static void testFileFunction(){
        File file = new File("F:");
        //获取指定目录下的文件和文件夹,返回字符串数组,结果不带盘符
        String[] str = file.list();
        for (String string : str) {
            System.out.println("结果不带盘符:"+string);
        }
        //获取指定目录下的文件和文件夹,返回file对象数组,结果带盘符
        File[] f = file.listFiles();
        for (File file2 : f) {
            System.out.println("结果带盘符:"+file2);
        }
        //列出当前电脑的所有盘符
        File[] fil = file.listRoots();
        for (File file2 : fil) {
            System.out.println("盘符:"+file2);
        }
    }
}

10.输入输出
10.1 File(目录和文件路径名的抽象表达形式)
10.2 字符流
10.3 字节流
10.4 缓冲流
10.5 编码
10.6 文档复制粘贴
10.7 集合和文件之间的转换
10.8 打印流
10.9 可变参数
10.10 数组转变为List集合
10.11 Properties
10.12 序列化流&&反序列化流

10.输入输出
10.1 File(目录和文件路径名的抽象表达形式)
10.2 字符流
10.3 字节流
10.4 缓冲流
10.5 编码
10.6 文档复制粘贴
10.7 集合和文件之间的转换
10.8 打印流
10.9 可变参数
10.10 数组转变为List集合
10.11 Properties
10.12 序列化流&&反序列化流

10.输入输出
10.1 File(目录和文件路径名的抽象表达形式)
10.2 字符流
10.3 字节流
10.4 缓冲流
10.5 编码
10.6 文档复制粘贴
10.7 集合和文件之间的转换
10.8 打印流
10.9 可变参数
10.10 数组转变为List集合
10.11 Properties
10.12 序列化流&&反序列化流

10.输入输出
10.1 File(目录和文件路径名的抽象表达形式)
10.2 字符流
10.3 字节流
10.4 缓冲流
10.5 编码
10.6 文档复制粘贴
10.7 集合和文件之间的转换
10.8 打印流
10.9 可变参数
10.10 数组转变为List集合
10.11 Properties
10.12 序列化流&&反序列化流

10.输入输出
10.1 File(目录和文件路径名的抽象表达形式)
10.2 字符流
10.3 字节流
10.4 缓冲流
10.5 编码
10.6 文档复制粘贴
10.7 集合和文件之间的转换
10.8 打印流
10.9 可变参数
10.10 数组转变为List集合
10.11 Properties
10.12 序列化流&&反序列化流

结果不带盘符:$RECYCLE.BIN
结果不带盘符:360CloudUI
结果不带盘符:360Downloads
结果不带盘符:BaiduYunDownload
结果不带盘符:IO
结果不带盘符:KwDownload
结果不带盘符:LETVdownload
结果不带盘符:System Volume Information
结果不带盘符:常用软件
结果不带盘符:迅雷下载
结果带盘符:F:$RECYCLE.BIN
结果带盘符:F:360CloudUI
结果带盘符:F:360Downloads
结果带盘符:F:BaiduYunDownload
结果带盘符:F:IO
结果带盘符:F:KwDownload
结果带盘符:F:LETVdownload
结果带盘符:F:System Volume Information
结果带盘符:F:常用软件
结果带盘符:F:迅雷下载
盘符:C:
盘符:D:
盘符:E:
盘符:F:
盘符:T:

10.1.2 常见操作

过滤文件名

package file;
/*public interface FilenameFilter实现此接口的类实例可用于过滤器文件名。
 * Abstract Window Toolkit 的文件对话框组件使用这些实例过滤 File 类的 list 方法中的目录清单。 


 * */
import java.io.File;
import java.io.FilenameFilter;

public class MyFileNameFilter implements FilenameFilter{
/*accept
boolean accept(File dir,
               String name)测试指定文件是否应该包含在某一文件列表中。 

参数:
dir - 被找到的文件所在的目录。
name - 文件的名称。 
返回:
当且仅当该名称应该包含在文件列表中时返回 true;否则返回 false。
*/
    @Override
    public boolean accept(File dir, String name) {
        // TODO Auto-generated method stub
        return new File(dir, name).isFile()&&name.endsWith(".java");
    }

}
package file;

import java.io.File;
import java.io.FilenameFilter;

/*
 * 需求:输出指定目录下的所有.java文件的名称
 * 
 * 思路:
 *         a: 封装目录
 *         b: 获取所有File对象(包含文件和文件夹)
 *         c: 获取到每一个File对象
 *         d: 判断该File对象 是否是 文件
 *             是:
 *                 判断是否是.java结尾的文件
 *                    是: 输出文件的名字
 *                    否: 不管
 *             否: 不管
 */
public class FileTest {

    public static void main(String[] args) {
        //方式1:
//        test();
        //自定义文件名过滤器
//        test2();
        //匿名内部类
        test3();

    }
    //方式一
    public static void test(){
        File file = new File("E:\");
        File[] ff = file.listFiles();
        for (File file2 : ff) {
            if(file2.isFile()&&file2.getName().endsWith(".java")){
                System.out.println("指定目录中后缀为.java的文件名:"+file2);
            }
        }
    }
    //方式二:自定义文件名过滤器
    public static void test2(){
        File file = new File("E:\");
        //我们在这里使用了自定义文件名过滤器
        File[] file1 = file.listFiles(new MyFileNameFilter());
        for (File file2 : file1) {
            System.out.println("符合规格的文件名:"+file2);
        }
    }
    //方式二:匿名内部类
    /*
    //封装目录
    File srcFile = new File("E:\");
    // 获取所有File对象(包含文件和文件夹)
    File[]  files = srcFile.listFiles(new MyFilenameFilter());
    
    //获取到每一个File对象
    for (File file : files) {
        //判断条件不用写了,因为条件在MyFilenameFilter器中写好了,得到的File数组 已经是一个过滤后的.java文件结尾的数组了
        // 输出文件的名字
        System.out.println(file.getName());
    }
    */
    public static void test3(){
        //封装目录
        File file = new File("E:\");
        File[] file1 = file.listFiles(new FilenameFilter() {
            
            @Override
            public boolean accept(File dir, String name) {
                // TODO Auto-generated method stub
                return new File(dir, name).isFile()&&name.endsWith(".java");
            }
        });
        for (File file2 : file1) {
            System.out.println("符合规定的文件名:"+file2);
        }
    }
}
文件名称的源代码过滤器解析
//封装目录 File srcFile = new File("E:\"); //获取所有File对象(包含文件和文件夹) File[] files = srcFile.listFiles(new MyFilenameFilter()); public File[] listFiles(FilenameFilter filter) {// filter -- new MyFilenameFilter() String ss[] = list(); // -- this.list() -- srcFile.list() -- 返回的所有文件夹和文件名称 if (ss == null) return null; ArrayList<File> files = new ArrayList<>(); for (String s : ss) // s -- 每一个文件或者文件夹 if ((filter == null) || filter.accept(this, s)) files.add(new File(s, this)); return files.toArray(new File[files.size()]); } public class MyFilenameFilter implements FilenameFilter { //过滤方法 @Override public boolean accept(File dir, String name) { //dir -- srcFile -- E:\ //name -- s -- 每一个文件或者文件夹 -- Demo.java return new File(dir, name).isFile() && name.endsWith(".java"); } }

10.输入输出
10.1 File(目录和文件路径名的抽象表达形式)
10.2 字符流
10.3 字节流
10.4 缓冲流
10.5 编码
10.6 文档复制粘贴
10.7 集合和文件之间的转换
10.8 打印流
10.9 可变参数
10.10 数组转变为List集合
10.11 Properties
10.12 序列化流&&反序列化流

10.输入输出
10.1 File(目录和文件路径名的抽象表达形式)
10.2 字符流
10.3 字节流
10.4 缓冲流
10.5 编码
10.6 文档复制粘贴
10.7 集合和文件之间的转换
10.8 打印流
10.9 可变参数
10.10 数组转变为List集合
10.11 Properties
10.12 序列化流&&反序列化流

10.输入输出
10.1 File(目录和文件路径名的抽象表达形式)
10.2 字符流
10.3 字节流
10.4 缓冲流
10.5 编码
10.6 文档复制粘贴
10.7 集合和文件之间的转换
10.8 打印流
10.9 可变参数
10.10 数组转变为List集合
10.11 Properties
10.12 序列化流&&反序列化流

修改指定文件夹中文件名

package file;

import java.io.File;
import java.io.FilenameFilter;

/*
 * 需求:将指定目录下所有文件的名称 改名
 * [www-itcast-cn]专治各种疼痛01.mp4  -->  专治各种疼痛.mp4
 * 
 * 思路:
 *         a: 封装目录
 *         b: 找到所有的文件
 *         c: 得到每一个文件
 *         d: 改名 renameTo(File newfile)
 *             创建出新文件的名字
 *                 1: 获取旧文件的名称
 *                 2: 获取新文件的名字
 *                 3: 封装新文件对象
 *             用新名字 替代 旧名字
 * 
 */
public class FileTest2 {

    public static void main(String[] args) {
        //方式一
        test();

    }
    //方式一:
    public static void test(){
        File file = new File("E:\");
        File[] str = file.listFiles();
        for (File file2 : str) {
            if(file2.isFile()){
                if(file2.getName().endsWith(".mp4")){
                    //获取旧文件名字
                    String oldName = file2.getName();
                    //获取新文件名字
                    String newName = oldName.substring(15, 21)+".mp4";
                    File f = new File(file, newName);
                    file2.renameTo(f);
                }
                
            }
        }
        method();
    }
    //尾缀为.mp4
    public static void method(){
        File file = new File("E:\");
        //获取尾缀为.mp4的文件
         File[] str = file.listFiles(new FilenameFilter() {
                    
            @Override
            public boolean accept(File dir, String name) {
                // TODO Auto-generated method stub
                return new File(dir, name).isFile()&&name.endsWith(".mp4");
            }
        });
        for (File file2 : str) {
                    System.out.println("符合规格文件名:"+file2);
        }
    }
}

10.输入输出
10.1 File(目录和文件路径名的抽象表达形式)
10.2 字符流
10.3 字节流
10.4 缓冲流
10.5 编码
10.6 文档复制粘贴
10.7 集合和文件之间的转换
10.8 打印流
10.9 可变参数
10.10 数组转变为List集合
10.11 Properties
10.12 序列化流&&反序列化流

递归

package file;
/*
 * 递归:方法内部调用本方法
 * 
 *         从前有座山,山里有个庙,庙里有一个老和尚,老和尚给小和尚讲故事,故事的内容是:
 *             从前有座山,山里有个庙,庙里有一个老和尚,老和尚给小和尚讲故事,故事的内容是
 *                 从前有座山,山里有个庙,庙里有一个老和尚,老和尚给小和尚讲故事,故事的内容是
 *                     从前有座山,山里有个庙,庙里有一个老和尚,老和尚给小和尚讲故事,故事的内容是
 *                         ...
 * 
 *         学习java -- 找工作 -- 娶媳妇 -- 生娃娃 -- 放羊 -- 长大了
 *             学习java -- 找工作 -- 娶媳妇 -- 生娃娃 -- 放羊 -- 长大了
 *                 学习java -- 找工作 -- 娶媳妇 -- 生娃娃 -- 放羊 -- 长大了
 *                     学习java -- 找工作 -- 娶媳妇 -- 生娃娃 -- 放羊 -- 长大了
 *                         。。。
 * 
 * 递归使用的时候,可能出现 java.lang.*Error异常, 内存溢出
 * 使用递归的注意事项:
 *         a: 递归程序必须要有 出口
 */
public class RecursionDemo {
    private static int a = 3;
    public static void main(String[] args) {
        //没有出口
//        show();
        //有出口
        show1();
        System.out.println(a);
    }
    public static void show(){
        System.out.println("show方法内部调用本方法,没有出口!");
        show();
    }
    public static void show1(){
        System.out.println("show方法内部调用本方法,没有出口!");
        a--;
        System.out.println(a);
        if(a >= 0){
            show1();
        }
    }
}

10.输入输出
10.1 File(目录和文件路径名的抽象表达形式)
10.2 字符流
10.3 字节流
10.4 缓冲流
10.5 编码
10.6 文档复制粘贴
10.7 集合和文件之间的转换
10.8 打印流
10.9 可变参数
10.10 数组转变为List集合
10.11 Properties
10.12 序列化流&&反序列化流

10.输入输出
10.1 File(目录和文件路径名的抽象表达形式)
10.2 字符流
10.3 字节流
10.4 缓冲流
10.5 编码
10.6 文档复制粘贴
10.7 集合和文件之间的转换
10.8 打印流
10.9 可变参数
10.10 数组转变为List集合
10.11 Properties
10.12 序列化流&&反序列化流

package file;
/*
 * 递归:方法内部调用本方法
 * 
 *         从前有座山,山里有个庙,庙里有一个老和尚,老和尚给小和尚讲故事,故事的内容是:
 *             从前有座山,山里有个庙,庙里有一个老和尚,老和尚给小和尚讲故事,故事的内容是
 *                 从前有座山,山里有个庙,庙里有一个老和尚,老和尚给小和尚讲故事,故事的内容是
 *                     从前有座山,山里有个庙,庙里有一个老和尚,老和尚给小和尚讲故事,故事的内容是
 *                         ...
 * 
 *         学习java -- 找工作 -- 娶媳妇 -- 生娃娃 -- 放羊 -- 长大了
 *             学习java -- 找工作 -- 娶媳妇 -- 生娃娃 -- 放羊 -- 长大了
 *                 学习java -- 找工作 -- 娶媳妇 -- 生娃娃 -- 放羊 -- 长大了
 *                     学习java -- 找工作 -- 娶媳妇 -- 生娃娃 -- 放羊 -- 长大了
 *                         。。。
 * 
 * 递归使用的时候,可能出现 java.lang.*Error异常, 内存溢出
 * 使用递归的注意事项:
 *         a: 递归程序必须要有 出口
 */
public class RecursionDemo {
    private static int a = 3;
    public static void main(String[] args) {
        //没有出口
//        show();
        //有出口
//        show1();
//        System.out.println(a);
        System.out.println(factorialMethod(10));
        System.out.println(test(20));
    }
    public static void show(){
        System.out.println("show方法内部调用本方法,没有出口!");
        show();
    }
    public static void show1(){
        System.out.println("show方法内部调用本方法,没有出口!");
        a--;
        System.out.println(a);
        if(a >= 0){
            show1();
        }
    }
    /*
     * 需求: 请使用递归的方式, 打印出5的阶乘
     * 
     * 思路:
     *         5! = 5*4!
     *         4! = 4*3!
     *         3! = 3*2!
     *         2! = 2*1!
     *         1! = 1;
     * 
     * 使用递归:
     *         a: 出口条件    1! = 1;
     *         b: 需找规律    n! = n * (n-1)!
     * 
     *     5 * 4 * 3 * 2 * 1 = 120
     * 
     * 
     *  作业: 求 10的阶乘
     */
    public static int factorialMethod(int num){
        //出口条件
        //判断传入阶乘参数为1,直接返回1,1的阶乘为1
        if(num==1){
            return 1;
        }else if (num==0) {
            return 0;
        }else if (num < 0) {
            System.out.println("对不起请你检查输入数字:");
            return 0;
        }else 
            return num*factorialMethod(num-1);
    }
    /*
     * 小兔子的问题 数列  (斐波那契数列)
     *     1,1,2,3,5,8,13,.....
     * 
     * 通过递归的方式,得到第20项的内容
     *                 number:6765
     * 
     * 递归:
     *         出口:
     *             知道第一项    1
     *             知道第二项    1
     *         规则:
     *             第N项的值     是N的 前两项的和
     *             f(n): 代表的第N项的值
     *             N的前一项: f(n-1)
     *             N的前二项: f(n-2)
     * 
     *             f(n) =     f(n-1) + f(n-2)                     
     * 
     */
    public static int test(int num){
        //出口条件
        //判断传入参数为1,直接返回1,
        if(num==1){
            return 1;
        }else if (num==0) {
            return 0;
        }else if (num < 0) {
            System.out.println("对不起请你检查输入数字:");
            return 0;
        }else 
            return test(num-1)+test(num-2);
    }
}

10.输入输出
10.1 File(目录和文件路径名的抽象表达形式)
10.2 字符流
10.3 字节流
10.4 缓冲流
10.5 编码
10.6 文档复制粘贴
10.7 集合和文件之间的转换
10.8 打印流
10.9 可变参数
10.10 数组转变为List集合
10.11 Properties
10.12 序列化流&&反序列化流

package file;

import java.io.File;

/*
 * 需求: 删除指定目录下的所有文件
 * 
 * 思路:
 *         a:封装目录
 *         b:获取目录下所有FIle对象
 *         c:获取到每一个File对象
 *         d:判断是否为文件夹
 *             是:递归, 调用本方法
 *             否:删除
 */
public class FileDelete {

    public static void main(String[] args) {
        //创建指定目录对象
        File file = new File("F:\src");
        test1(file);
    }
    
    public static void test1(File file){
        //获取文件目录
        File[] f = file.listFiles();
        //发现,如果要删除的文件是受保护的文件或者是系统文件,这个时候,f返回的内容为null
        //为了 解决该文件,  在使用前,判断files数组是否为空即可。
        if(f != null){
            for (File file2 : f) {
                //判断文件是否为文件夹
                if(file2.isDirectory()){
                    //递归
                    test1(file2);
                }else {
                    boolean flag = file2.delete();
                    System.out.println("删除文件成功:"+flag);
                }
            }
        }
        //上面我们只是把文件夹中的文件删除了,而文件夹还在,我们应该怎么删除文件夹呢
        System.out.println("删除文件夹:"+file.getName()+"--"+file.delete());
        
    }

}

删除文件成功:true
删除文件成功:true
删除文件成功:true
删除文件成功:true
删除文件成功:true
删除文件夹:itcast_01--true
删除文件成功:true
删除文件成功:true
删除文件成功:true
删除文件夹:itcast_02--true
删除文件成功:true
删除文件成功:true
删除文件夹:itcast_03--true
删除文件夹:cn--true
删除文件夹:src--true

package file;

import java.io.File;
import java.io.FilenameFilter;

/*
 * 获取指定目录下的 所有java文件的绝对路径(包含子文件夹中的java文件)
 * 
 * 递归:
 *         a: 封装目录
 *         b: 获取当前目录下的所有File对象 
 *         c: 获取到每一个File对象
 *         d: 判断File 是否是 目录
 *             是:     递归, 回到b的步骤
 *             否:
 *                 判断是否是java文件
 *                     是:输出java文件的绝对路径
 *                     否:不管
 */
public class FileGetAbsolutePath {

    public static void main(String[] args) {
        File file = new File("F:\src");
        test(file);
    }
    public static void test(File file){
        //获取指定文件目录
        File[] f = file.listFiles();
        //系统文件或受保护文件,返回null
        if(f != null){
            //遍历文件数组
            for (File file2 : f) {
                //判断是否为目录,如果是目录递归,不是获取绝对路径
                if(file2.isDirectory()){
                    test(file2);
                }else {
                    if(file2.getName().endsWith(".java"));
                    System.out.println("如果是Java文件,获取绝对路径:"+file2.getAbsolutePath());
                }
            }
        }
        
    }
}

如果是Java文件,获取绝对路径:F:srccnitcast_01FileDemo.java
如果是Java文件,获取绝对路径:F:srccnitcast_01FileDemo2.java
如果是Java文件,获取绝对路径:F:srccnitcast_01FileTest.java
如果是Java文件,获取绝对路径:F:srccnitcast_01MyFilenameFilter.java
如果是Java文件,获取绝对路径:F:srccnitcast_01文件名称过滤器的源代码解析.txt
如果是Java文件,获取绝对路径:F:srccnitcast_02DiGuiDemo.java
如果是Java文件,获取绝对路径:F:srccnitcast_02DiGuiDemo2.java
如果是Java文件,获取绝对路径:F:srccnitcast_02RabbitTest.java
如果是Java文件,获取绝对路径:F:srccnitcast_03DeleteFileTest.java
如果是Java文件,获取绝对路径:F:srccnitcast_03GetFilePathTest.java

10.2 字符流

10.2.1 字符输出流

10.输入输出
10.1 File(目录和文件路径名的抽象表达形式)
10.2 字符流
10.3 字节流
10.4 缓冲流
10.5 编码
10.6 文档复制粘贴
10.7 集合和文件之间的转换
10.8 打印流
10.9 可变参数
10.10 数组转变为List集合
10.11 Properties
10.12 序列化流&&反序列化流

package IO.writer;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

/*
 * IO流:用来处理各种设备之间数据传递问题
 * 
 *         流向分类:
 *             输入流        
 *             输出流        
 *         
 *         数据类型:
 *             字节流    
 *                 字节输入流:    InputStream
 *                 字节输出流:  OutputStream
 *             字符流
 *                 字符输入流:    Reader    
 *                 字符输出流:    Writer
 * 
 *         IO的分类? 答的是数据类型的分类
 * 
 * 需求: 我要把数据写入到文本文件中   "把红灯当做猴屁股了" --> fw.txt
 * 
 * 分析:
 *         a: 文本文件 --  字符流
 *         b: 写入数据 --     输出流 
 *         综上所述:  字符输出流  -- Writer
 * 
 *  发现Writer是抽象类,不能创建对象, 所以使用子类 FileWriter来创建对象
 *  java.lang.Object
          java.io.Writer
              java.io.OutputStreamWriter
                  java.io.FileWriter

 * FileWriter
 *         构造函数:
 *             public FileWriter(File file) : 给定一个File对象, 创建字符输出流
 *             public FileWriter(String fileName) : 给定一个字符串, 创建字符输出流
 * 
 * 面试题: 
 *         1、FileWriter fw = new FileWriter("fw.txt",true);
 *             a: 通过系统操作, 如果fw.txt文件不存在,自动给我们创建出来
 *                如果文件文件fw.txt存在,这时候看第二个参数 是否为true
 *                 true: 开启追加模式, 在原有数据的后面添加新数据
 *                 false:就是数据的覆盖操作,  把原有的内容清空,写入新的数据
 * 
 *             b: 创建了一个字符输出流对象
 *             c: 把 字符输出流对象  指向了 文本文件 fw.txt
 * 
 *         2、请问flush()和close()的区别?
 * 
 *             flush: 使用完毕后, 可以继续写入数据
 *             close:使用完毕后, 流就关闭了,流对象变成了垃圾,不可以继续操作
 * 
 * 把大象从冰箱中 拿出来分几步?
 * 1: 打开冰箱门
 * 2: 拽出大象
 * 3: 关闭冰箱门
 * 
 * 把数据写入到文件里 分几步?
 * 1: 创建字符输出流对象     FileWriter fw = new FileWriter("fw.txt");
 * 2: 把数据写入到文件          fw.write();
 * 3: 释放字符输出流对象     fw.close();
 */
/*
 * FileWriter: 字符输出流
 * 
 *  void write(char[] cbuf) 写入字符数组。 
 *    abstract  void write(char[] cbuf, int startIndex, int len) 写入字符数组的某一部分。 
 *    void write(int c) 写入单个字符。 
 *     void write(String str) 写入字符串。 
 *     void write(String str, int startIndex, int len) 写入字符串的某一部分。 
 */
/*
 * 小问题:
 *         1: 内容覆盖了,  我想要的是 内容的追加  构造函数来解决问题
 *             public FileWriter(File file, boolean append)
 *             public FileWriter(String fileName, boolean append)
 * 
 *         2: 我想换行
 *             Windows: 

 *             Linux unix : 

 *             macOS : 
 */
public class FileWriterDemo {

    public static void main(String[] args) throws IOException {
        //将指定字符写入到指定文本
//        testWriter();
        //字符输出流的练习
//        writerPractice();
        //覆盖,追加以及换行符的使用
//        writerTest();
        writerException();
    }
    //把给定字符串,写入到fw.txt文件
    public static void testWriter() throws IOException{
        //创建字符输出流对象
        File f = new File("F:\IO\fw.txt");
        //当我们给定的目录中没有fw.txt文件时,会自动创建,如果存在会根据后面的Boolean值,决定是覆盖false还是追加true内容
        FileWriter fw = new FileWriter(f,true);
        //写入数据
        fw.write("游晓静,我会回来的!");
        //此时我们查看文件发现数据并没有被写入,为什么 数据没有写入进去呢?
        //因为我们使用的字符流,一个字符对应2个字节,文件的基本单位是字节, 我们不能将2个字节的数据 直接存储
        //把这些数据 写入到了  缓冲区中,  怎么把缓冲区里内容写入到文件中呢?  
        // 通过 flush() 把缓冲区的数据,写入到指定的文件中,flush之后还可以继续输出字符
        fw.flush();
        fw.write("我一定会回来的!");
        //释放资源
        //close方法只执行前,它会自动的调用一次flush方法
        fw.close();
        //当流被关闭后,再次写入字符,后出现IOException   Stream closed
        //fw.write("11");
    }
    //字符输出流的练习
    public static void writerPractice() throws IOException{
        //创建字符读入流对象
        FileWriter fw = new FileWriter("F:\IO\fw.txt", true);
        //创建字符数组,字符串
        char[] ch = {'我','爱','你',',','真','的'};
        String str = "我真的爱你!";
        //写入字符数组
        fw.write(ch);
        //写入字符数组一部分,三个参数,字符数组名称,开始脚标,长度,注意脚标越界异常,第二个参数和第三个参数相加<=数组长度
        fw.write(ch, 2, 4);
        fw.flush();
        //写入字符串
        fw.write(str);
        //写入字符串一部分,和上面写入字符数组一样,注意脚标越界异常
        fw.write(str, 2, 3);
        fw.flush();
        //写入单个字符
        fw.write('静');
        fw.close();
    }
    //覆盖和追加,以及换行符的运用
    public static void writerTest() throws IOException{
        FileWriter fwC = new FileWriter("F:\IO\fw.txt", false);
        //覆盖操作
        fwC.append('静');
        fwC.flush();
        FileWriter fwA = new FileWriter("F:\IO\fw.txt", true);
        //追加操作
        fwA.append("
");
        fwA.append('静');
        fwA.flush();
        //循环写入数据
        for (int i = 0; i < 10; i++) {
            fwA.append("jing");
            fwA.append("
");
            fwA.flush();
        }
        //关闭流,释放资源,我们打开了两个流,所以执行两次关闭流操作
        fwA.close();
        fwC.close();
    }
    /*
     * FileWriter的异常处理
     */
    public static void writerException(){
        FileWriter fw = null;
        try {
            fw = new FileWriter("F:\IO\fw.txt");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            fw.write("静");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            fw.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //连贯练习
        FileWriter fw1;
        try {
            //使用这种方式创建字符输出对象,如果已经才在文档,默认是覆盖操作,也就是构造函数第二个参数默认是false
            fw1 = new FileWriter("F:\IO\fw.txt");
            fw1.write("奋斗!");
            fw1.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //终极写法
        FileWriter fwri = null;
        try {
            fwri = new FileWriter("F:\IO\fw.txt");
            fwri.write("奋斗终生!");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            try {
                fwri.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
                
    }
}

 10.2.2 字符输入流

10.输入输出
10.1 File(目录和文件路径名的抽象表达形式)
10.2 字符流
10.3 字节流
10.4 缓冲流
10.5 编码
10.6 文档复制粘贴
10.7 集合和文件之间的转换
10.8 打印流
10.9 可变参数
10.10 数组转变为List集合
10.11 Properties
10.12 序列化流&&反序列化流

用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。要自己指定这些值,可以先在 FileInputStream 上构造一个 InputStreamReader。

FileReader 用于读取字符流。要读取原始字节流,请考虑使用 FileInputStream

package IO.reader;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

/*
 * 需求: 读取fw.txt中数据    打印到控制台(一次读取一个字符)
 * 
 * 分析: 文本文件: 字符流
 *              读取数据: 输入流
 *         综上所述:  字符输入流 
 *            
 * FileReader:
 *         构造函数:
 *             public FileReader(File file) : 通过给定的File对象 ,创建一个字符输入流对象
 *            public FileReader(String fileName): 通过给给定的字符串, 创建一个字符输入流对象
 *
 *    操作字符输入流的步骤:
 *    1: 创建字符输入流对象  (需要注意,使用的文件必须要提前存在)
 *  2: 读取数据
 *  3: 释放资源,关闭流对象
 *
 */
/*
 * 需求: 读取fw.txt中数据    打印到控制台(一次读取一个字符数组)
 * 
 * 分析: 文本文件: 字符流
 *              读取数据: 输入流
 *         综上所述:  字符输入流 
 * 
 * public int read(char[] cbuf)
 * 
 * 
 * 操作字符输入流的步骤:
 *    1: 创建字符输入流对象  (需要注意,使用的文件必须要提前存在)
 *  2: 读取数据
 *  3: 释放资源,关闭流对象
 *  
 *  
 *  length = fr.read(chs);
 *  length: 本次读取到的实际字符的个数
 */
public class FileReaderDemo {

    public static void main(String[] args) throws IOException {
        //文件输入流
//        readerTest();
        //读取指定字符长度
//        readerPractice();
        //读取相对路径下的一个文件,输出打印
        readerDemo();

    }
    // 读取fw.txt中数据    打印到控制台(一次读取一个字符)
    public static void readerTest() throws IOException{
        //创建字符输入流对象,如果没有这个文件会提示FileNotFoundException,文件对象找不到异常
        File file = new File("F:\IO\fw.txt");
        FileReader fr = new FileReader(file);
        //fr.read(),一次读取一个字符,所以没读一次可以输出一次
        /*返回:  读取的字符,如果已到达流的末尾,则返回 -1 
         * java遵循unicode编码,所以每个字符对应Unicode编码表中的数字*/
//        int ch = fr.read();
//        System.out.println(ch);
//        int ch1 = fr.read();
//        System.out.println(ch1);
        //实际上,我们可能读取的是很多的字符,不可能是已知的,也不能每次都System.out,那么循环就成了最好的解决办法
        //过渡版本
//        int ch = fr.read();
//        //判断没有读到流的末尾
//        while (ch != -1) {
//            System.out.println(ch);
//            ch = fr.read();
//        }
        //观察上面的书写形式我们发现简化了很多,但是我们看到最上边和最下边都有读的操作,这是不是有代码重复的嫌疑呢,可不可以只写一次呢
        //最终版本
        int ch = 0;
        while ((ch = fr.read()) != -1) {
            System.out.println(ch);
        }
        //关闭流,释放资源
        fr.close();
    }
    //一次读取多个字符,即读取字符到字符数组,字符数组是一个读取到的字符的缓冲区
    public static void readerPractice() throws IOException{
        FileReader fr = new FileReader("F:\IO\fw.txt");
        //指定一次读取字符数组长度
        /*char[] ch = new char[30];
        int length = fr.read(ch);
        System.out.println("输出自负输入流读取到的字符长度"+length);
        System.out.println(String.valueOf(ch, 0, length));
        length = fr.read(ch);
        System.out.println("输出自负输入流读取到的字符长度"+length);
        System.out.println(String.valueOf(ch, 0, length));
        length = fr.read(ch);
        System.out.println("输出自负输入流读取到的字符长度"+length);
        System.out.println(String.valueOf(ch, 0, length));
        length = fr.read(ch);
        System.out.println("输出自负输入流读取到的字符长度"+length);
        System.out.println(String.valueOf(ch, 0, length));
        //使用这种方式的弊端,1,我们不知道源文件的字符长度,所以不知道该有多少输出语句,所以当流读取到末尾继续读会java.lang.StringIndexOutOfBoundsException,因为读取返回-1,而数组是没有脚本为-1的
        length = fr.read(ch);
        System.out.println("输出自负输入流读取到的字符长度"+length);
        System.out.println(String.valueOf(ch, 0, length));*/
        //通过操作上面我们知道这种方式既繁琐,又不可取,那么我们现在就要考虑一下循环了
    /*    char[] ch = new char[30];
        int length = fr.read(ch);
        while (length != -1) {
            System.out.println("读取到的长度:"+length);
            System.out.println(String.valueOf(ch, 0, length));
            //注意这里我们有时会忘记把读取到的长度赋值给length,这会造成死循环
            length = fr.read(ch);
        }*/
        //上面的代码我们仍能看出,冗余
        char[] ch = new char[1024];// 指定一次读取字符的个数 1024代表一次最多可以读取1024个字符,通常开发中写成1024的整数倍
        int length = 0;
        while ((length = fr.read(ch)) != -1) {
            System.out.println("读取到的字符长度:"+length);
            System.out.println(String.valueOf(ch, 0, length));
        }
        //关闭流,释放资源
        fr.close();
    }
    /*
     * 将FileWriterDemo.java文件中的内容 获取出来, 在控制台打印(一次获取一个字符)
     * 
     * 操作字符输入流的步骤:
     * 1: 创建字符输入流对象
     * 2: 读取数据
     * 3: 释放资源
     */
    public static void readerDemo() throws IOException{
        FileReader fr = new FileReader("src/IO/writer/FileWriterDemo.java");
        char[] ch = new char[1024];
        int length = 0;
        while ((length = fr.read(ch)) != -1) {
            System.out.println("读取到的字符长度:"+length);
            System.out.println(String.valueOf(ch, 0, length));
        }
        //关闭流,释放资源
        fr.close();
    }
}

10.2.3 字符输入流和字符输出流的合并联系--即复制 粘贴的操作

package IO.reader;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/*  FileWriterDemo.java 里面的内容, 写入到 E:\Demo.java中
*  
*  思路:
*      a: 数据源 -- 获取数据 -- 输入流 -- Reader -- FileReader -- FileWriterDemo.java
*      b: 目的地 -- 写入数据 -- 输出流 -- Writer -- FileWriter -- E:\Demo.java
*      c: 创建字符缓冲区  1024大小
*      d: 通过循环操作,进行数据的读取与 写入
*          先读数据
*          再写数据
*      e: 释放资源    
*  
*/
public class FileReaderToWriterDemo {

    public static void main(String[] args) throws IOException {
        test();

    }
    public static void test() throws IOException{
        //创建源文件输入流对象和输出流对象
        FileReader fr = new FileReader("F:\IO\fw.txt");
        FileWriter fw = new FileWriter("F:\IO\f.txt");
        char[] ch = new char[1024];
        int length = 0;
        while ((length = fr.read(ch)) != -1) {
            fw.write(ch, 0, length);
        }
        fr.close();
        fw.close();
    }
}

10.3 字节流

10.3.1 字节输入流

package IO.FileInputStream;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/*
 * FileInputStream : 用于读取诸如图像数据之类的原始字节流
 * 
 *  字节输入流的操作步骤:
 *      a: 创建字节输入流对象
 *      b: 获取数据
 *      c: 释放资源
 */
public class FileInputStreamDemo {

    public static void main(String[] args) throws IOException {
        //字节流的入手
        fileInputStreamTest();

    }
    //字节输入流的入手
    public static void fileInputStreamTest() throws IOException{
        FileInputStream fis = new FileInputStream("F:\IO\io\b.txt");
        //方式一:一次读取一个字节
//        int ch = 0;
//        while ((ch=fis.read()) != -1) {
//            System.out.println(ch);
//        }
        //方式二:一次读取一定长度的字节数组
        byte[] b = new byte[1024];
        int length = 0;
        while ((length = fis.read(b)) != -1) {
            System.out.println("字节长度"+length);
            System.out.println("得到字节数组的一部分:"+new String(b, 0, length));
        }
        //关闭流,释放资源
        fis.close();
    }
}

10.3.2 字节输出流

package IO.FileOutPutStream;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/*
 * IO流
 *         字符流
 *             字符输入流 -- Reader
 *             字符输出流 -- Writer
 *         字节流
 *             字节输入流 -- InputStream
 *             字节输出流 -- OutputStream
 * 
 *  需求: 使用字节输出流  向文本文件中写入 数据
 * 
 *  FileOutputStream :用于写入诸如图像数据之类的原始字节的流
 *      写入数据:
 *            public abstract void write(int b) :  写入一个字节
 *          public void write(byte[] b) : 写入一个字节数组
 *            public void write(byte[] b,int off, int len) 写入一个字节数组的一部分

 *  
 *  使用字节输出流的步骤:
 *      a: 创建字节输出流对象
 *      b: 写入数据
 *      c: 释放资源
 */
public class FileOutputStreamDemo {

    public static void main(String[] args) throws IOException {
        //字节输出流入手
        fileOutputStreamDemo();

    }
    public static void fileOutputStreamDemo() throws IOException{
        FileOutputStream fos = new FileOutputStream("F:\IO\Demo.java");
        //写入一个字节
        fos.write(97);
        fos.flush();
        //写入一个字节数组
        byte[] b = new byte[]{97,98,99,100,101};
        fos.write(b);
        fos.flush();
        //写入字节数组的一部分,三个参数为字节数组   写去字节数组起始脚标   写入长度
        fos.write(b, 0, 3);
        fos.flush();
        //字符串写入---字符串转换成字节数组
        fos.write("mnbvc".getBytes(), 0, "abcde".length());
        fos.flush();
        fos.close();
    }
}

10.3.3 字节输入输出流的联合联系,复制粘贴(注意:复制粘贴意味着哪怕目的地已经有同名文件也会覆盖)

package IO.FileOutPutStream;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class FileOutputStreamTest {

    public static void main(String[] args) throws IOException {
        //复制图片
//        imgTest();
        //复制音乐
//        mp3Test();
        //测试字符流操作非字符内容---不可行
//        charStreamTest();
        //测试字节流操作文档---可行
        byteStreamTest();
    }
    /*
     * 使用字节流  复制照片
     *  需要: 把 F:\360wallpaper.jpg 复制到 项目根目录下的 copy.bmp
     *  数据源: F:\360wallpaper.jpg -- 字节输入流 -- FileInputStream
     *  目的地: copy.bmp -- 字节输出流  -- FileOutputStream
     */
    public static void imgTest() throws IOException{
        //数据源
        FileInputStream fis = new FileInputStream("F:\360wallpaper.jpg");
        //目的地
        FileOutputStream fos = new FileOutputStream("copy.bmp");
        //定义一个字节数组,作为每次读和写的长度标准
        byte[] b = new byte[5];
        int length = 0;
        while ((length = fis.read(b))!= -1) {
            fos.write(b, 0, length);
        }
        fis.close();
        fos.close();
    }
    /*
     * 需求: 把 F:\重案六组1.mp4  拷贝  到 项目跟目下  小苹果.mp4中
     *  数据源:F:\重案六组1.mp4 -- 字节输入流 -- FileInputStream
     *  目的地:    小苹果.mp4 -- 字节输出流 -- FileOutputStream
     */
    public static void mp3Test() throws IOException{
        FileInputStream fis = new FileInputStream("F:\重案六组1.mp4");
        FileOutputStream fos = new FileOutputStream("小苹果.mp4");
        //定义一个字节数组,作为缓存
        byte[] b = new byte[1024];
        int length = 0;
        while ((length = fis.read(b))!= -1) {
            fos.write(b, 0, length);
        }
        //关闭流,释放资源
        fis.close();
        fos.close();
    }
    /*
     * 问: 
     *         字节流  能操作,文本文件吗?  
     *         能
     * 
     *         测试: 字符流 能操作,非文本文件(图片、音视频)吗?
     *         不能,会出现数据的丢失,导致文件损坏
     * 
     *         字节流: 用于读取、写入诸如图像数据之类的原始字节流(图片、音视频)  二进制文件
     *         字符流:用来读取、写入字符文件的便捷类(文本文件)
     *  --------------------------
     *  使用字符流   复制照片
     *  需要: 把  F:\360wallpaper.jpg 复制到 项目根目录下的 copy.bmp
     *  数据源: F:\360wallpaper.jpg -- 字符输入流 -- FileReader
     *  目的地: copy.bmp -- 字符输出流  -- FileWriter
     */
    public static void charStreamTest() throws IOException{
        //创建字符输入流和字符输出流
        FileReader fr = new FileReader("F:\360wallpaper.jpg");
        FileWriter fw = new FileWriter("copy1.bmp");
        //定义字符数组,作为缓存
        char[] ch = new char[1024];
        int length = 0;
        while ((length = fr.read(ch))!= -1) {
            //fw.write(String.valueOf(ch), 0, length);
            fw.write(ch, 0, length);
        }
        fr.close();
        fw.close();
        System.out.println("通过操作我们看到,项目根目录下出现了copy1.bmp,但是打开的时候却不能正常观看,这说明字符流操作非字符内容造成数据丢失");
    }
    /*
     * 需求:把 F:\Demo.java中的内容     拷贝到 项目根目录下的 copy.java中
     * 数据源:F:\Demo.java -- 字节输入流 -- InputStream -- FileInputStream    
     * 目的地: copy.java -- 字节输出流 -- OutputStream -- FileOutputStream 
     */
    public static void byteStreamTest() throws IOException{
        FileInputStream fis = new FileInputStream("F:\Demo.java");
        FileOutputStream fos = new FileOutputStream("Demo.java");
        byte[] b = new byte[1024];
        int len = 0;
        while ((len = fis.read(b))!= -1) {
            fos.write(b, 0, len);
        }
        fis.close();
        fos.close();
    }
}

10.4 缓冲流

10.4.1 字节缓冲流

10.4.1.1 字节输入缓冲流

package IO.BufferedInputStream;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/*
 * (高效)字节缓冲输入流:BufferedInputStream
 * 
 * 使用高效的流 : 来读取指定文件中的数据
 * 
 * (高效)字节缓冲输入流操作步骤:
 *         a:创建 (高效)字节缓冲输入流 对象
 *         b:读取数据
 *         c:释放资源
 */
public class BufferedInputStreamDemo {

    public static void main(String[] args) throws IOException {
        bufferInputStreamTest();

    }
    public static void bufferInputStreamTest() throws IOException{
        //a:创建 (高效)字节缓冲输入流 对象
        //public BufferedInputStream(InputStream in)
        //InputStream is = new FileInputStream("bos.txt");
        //BufferedInputStream bis = new BufferedInputStream(is);
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\Demo.java"));
        byte[] b = new byte[1024];
        int len = 0;
        while ((len = bis.read(b))!= -1) {
            System.out.println("读取的长度:"+len);
            System.out.println("读取到的内容:"+(new String(b, 0, len)));
        }
        bis.close();
    }
    
}

10.4.1.2 字节输出缓冲流

package IO.BufferedOutputStream;

import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/*
 * java中 提供了 高效的流
 * 
 *         数据类型分类:
 *             字节流:
 *                 字节输入流: InputStream
 *                     (高效)字节缓冲输入流:BufferedInputStream        
 *                 字节输出流: OutputStream
 *                     (高效)字节缓冲输出流: BufferedOutputStream
 *             字符流:
 *                 字符输入流: Reader
 *                     (高效)字符缓冲输入流: BufferedReader
 *                 字符输出流: Writer
 *                     (高效)字符缓冲输出流: BufferedWriter
 * 
 *  使用高效的流 : 来完成数据写入到 文件中
 *  
 *  需求:使用字节高效的流, 向文本文件中 写入 字节数据 
 *      (高效)字节缓冲输出流
 *  
 *      a: 创建 (高效)字节缓冲输出流对象
 *      b: 写入数据
 *      c: 释放资源
 */
public class BufferedOutputStreamDemo {

    public static void main(String[] args) throws IOException {
        bufferedOutputStreamTest();

    }
    public static void bufferedOutputStreamTest() throws IOException{
        //创建 (高效)字节缓冲输出流对象
        //public BufferedOutputStream(OutputStream out)
        //OutputStream os = new FileOutputStream("bos.txt");
        //BufferedOutputStream bos = new BufferedOutputStream(os);
        //创建字节缓冲流对象,设置当文件存在时,追加不覆盖
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\Demo.java", true));
        //要输出的字节
        byte[] b = new byte[]{97,98,99,100,101,102};
        bos.write(b, 0, b.length);
        bos.close();
    }
}

10.4.1.3 字节输出输入缓冲流联合联系

package IO.BufferedOutputStream;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class BufferedInputOutputStreamTest {

    public static void main(String[] args) throws IOException {
        //图片复制
//        imgTest();
        //文档复制
//        fileTest();
        Long start = System.currentTimeMillis();
//        test1();
//        test2();
//        test3();
        test4();
        Long end = System.currentTimeMillis();
        Long time = end-start;
//        System.out.println("普通流一次一个字节共耗时:"+time);106782
//        System.out.println("普通流一次一个字节数组共耗时:"+time);148
//        System.out.println("高效流一次一个字节共耗时:"+time);1076
//        System.out.println("高效流一次一个字节数组共耗时:"+time);113

    }
    /*
     *     使用字符缓冲流  复制文本文件
     *  需要: 把 F:360wallpaper.jpg 复制到 项目根目录下的 copy.bmp
     *  数据源:F:360wallpaper.jpg -- 字节输入流 -- FileInputStream -- BufferedInputStream
     *  目的地: copy.bmp -- 字节输出流  -- FileOutputStream -- BufferedOutputStream
     */
    public static void imgTest() throws IOException{
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\360wallpaper.jpg"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.bmp"));
        byte[] b = new byte[1024];
        int len = 0;
        while ((len = bis.read(b)) != -1) {
            bos.write(b, 0, len);
        }
        bis.close();
        bos.close();
    }
    /*
     * 使用字节缓冲流
     * 需求:把 F:\Demo.java中的内容     拷贝到 项目根目录下的 copy.java中
     * 数据源: F:\Demo.java -- 字节输入流 -- 字节缓冲输入流 -- BufferedInputStream 
     * 目的地:copy.java -- -- 字节输出流 -- 字节缓冲输出流  -- BufferedOutputStream
     */
    public static void fileTest() throws IOException{
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\Demo.java"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("demo.java"));
        byte[] b = new byte[1024];
        int len = 0;
        while ((len = bis.read(b))!= -1) {
            bos.write(b, 0, len);
        }
        bis.close();
        bos.close();
    }
    /*
     *  通过四种方式,复制视频文件
     *  
     *  把F:\重案六组1.mp4 拷贝到  项目根目录下  copy.mp4
     *  看4种方式的效率
     *  
     *  数据源:    F:\重案六组1.mp4
     *  目的地:    copy.mp4
     *  
     *  字节流
     *      普通的流: 
     *          一次一个字节        共耗时:133065 毫秒
     *          一次一个字节数组    共耗时:          213 毫秒
     *      高效的流:
     *          一次一个字节        共耗时:      1050 毫秒
     *          一次一个字节数组    共耗时:             65 毫秒
     */
    public static void test1() throws IOException{
        //创建字节流对象
        FileInputStream fis = new FileInputStream("F:\重案六组1.mp4");
        FileOutputStream fos = new FileOutputStream("copy.mp4");
        int len = 0;
        while ((len = fis.read())!= -1) {
            fos.write(len);
        }
        //关闭流,释放资源
        fis.close();
        fos.close();
    }
    public static void test2() throws IOException{
        //创建字节流对象
        FileInputStream fis = new FileInputStream("F:\重案六组1.mp4");
        FileOutputStream fos = new FileOutputStream("copy.mp4");
        //定义读取字节长度数组
        byte[] b = new byte[1024];
        int len = 0;
        while ((len = fis.read(b))!= -1) {
            fos.write(b, 0, len);
        }
        //关闭流,释放资源
        fis.close();
        fos.close();
    }
    public static void test3() throws IOException{
        //创建字节缓冲流对象
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\重案六组1.mp4"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.mp4"));
        //定义int类型变量作为字节输入流读取的字节
        int len = 0;
        while ((len = bis.read())!=-1) {
            bos.write(len);
        }
        bis.close();
        bos.close();
    }
    public static void test4() throws IOException{
        //创建字节缓冲流对象
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\重案六组1.mp4"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.mp4"));
        byte[] b = new byte[1024];
        //定义int类型变量作为字节输入流读取的字节长度
        int len = 0;
        while ((len = bis.read(b))!=-1) {
            bos.write(b, 0, len);
        }
        bis.close();
        bos.close();
    }
}

10.4.2 字符缓冲流

10.4.2.1 字符输入缓冲流

package IO.BufferedReader;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

/*
 * BufferedReader
 *         public String readLine() : 读取一行文本内容,但是不包含换行符
 *
 *    把 Demo.java中的 数据 读取出来 (使用BufferedReader的特有方法 readLine() )
 *
 *    高效的字符缓冲输入流的操作步骤:
 *        a: 创建字符缓冲输入流对象
 *        b: 读取数据
 *        c: 释放资源
 */
public class BufferedReaderDemo {

    public static void main(String[] args) throws IOException {
        bufferedReaderTest();

    }
    public static void bufferedReaderTest() throws IOException{
        //创建字符输入缓冲流对象
        BufferedReader br = new BufferedReader(new FileReader("F:\Demo.java"));
        //读取数据
        // String line = br.readLine();
        // System.out.println(line);
        //
        // line = br.readLine();
        // System.out.println(line);
        //
        // line = br.readLine();
        // System.out.println(line);
        //
        // line = br.readLine();
        // System.out.println(line);
        //定义字符串对象作为字符输入缓冲流对象读取后返回的行
        String line = null;
        while ((line = br.readLine())!= null) {
            System.out.println(line);
        }
        br.close();
    }

}

10.4.2.2 字符输出缓冲流

package IO.BufferedWriter;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

/*
 * BufferedWriter:
 *         public void newLine() : 换行符
 * 
 * BufferedWriter写入数据的三部曲:
 *         write();
 *         newLine();
 *         flush();
 * flush() 
          刷新该流的缓冲。 
 void newLine() 
          写入一个行分隔符。 

 * 向文本文件中写入指定的数据
 * 
 * 数据源:
 *         数据
 * 目的地:
 *         文本文件
 * 
 * 操作 高效 字符缓冲输出流的步骤:
 *     a: 创建字符缓冲输出流对象
 *     b: 写入数据
 *     c: 释放资源
 */
public class BufferedWriterDemo {

    public static void main(String[] args) throws IOException {
        bufferedWriterTest();

    }
    public static void bufferedWriterTest() throws IOException{
        //创建字符输出缓存流的对象,指定目录中没有文件会先创建文件
        BufferedWriter bw = new BufferedWriter(new FileWriter("F:\Demo.txt"));
        //写入数据
        bw.write("Hello");
        //换行
        bw.newLine();
        //刷新该留=流的缓冲
        bw.flush();
        //循环输入
        for (int i = 0; i < 10; i++) {
            bw.write("人间正道是沧桑!");
            bw.newLine();
            bw.flush();
        }
        //关闭流
        bw.close();
    }
}

10.4.2.3 字符缓冲流练习

package IO.BufferedWriter;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/*
 * 使用高效的字符缓冲流, 来 拷贝文件
 * 需求:把 F:\Demo.java中的内容     拷贝到 项目根目录下的 copy.java中
 * 数据源:F:\Demo.java -- 字符输入流 -- 字符缓冲输入流 -- BufferedReader
 * 目的地:  copy.java -- 字符输出流  -- 字符缓冲输出流 -- BufferedWriter
 */
public class BufferedReaderWriterDemo {

    public static void main(String[] args) throws IOException {
        test();

    }
    public static void test() throws IOException{
        //创建字符缓冲流
        BufferedReader br = new BufferedReader(new FileReader("F:\Demo.java"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("copy.java"));
        byte[] b = new byte[1024];
        String line = null;
        while ((line = br.readLine())!=null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        //关闭流
        br.close();
        bw.close();
    }
}

 10.4.3 中间流

package IO.inputStreamReader;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

/*
 * InputStreamReader 是字节流通向字符流的桥梁
 * InputStreamReader(InputStream in) 
          创建一个使用默认字符集的 InputStreamReader。
 * 
 * 需求: 通过键盘输入数据, 写入到 abc.txt 文本文件中 (使用转换流)
 * 
 * 数据源:
 *         键盘输入    -- System.in -- InputStream -- 
 *                     <--  InputStreamReader -->
 *                     -- BufferedReader --readLine()
 * 目的地:
 *          abc.txt  文本文件
 */
public class InputStreamReaderDemo {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
//        test1();
        test2();
    }
    public static void test1() throws IOException{
        //创建数据源流
        InputStream is = System.in;
        //创建中间流
        InputStreamReader isr = new InputStreamReader(is);
        //创建字符缓冲流
        BufferedReader fr = new BufferedReader(isr);
        BufferedWriter bw = new BufferedWriter(new FileWriter("abc.txt"));
        String line = null;
        while ((line = fr.readLine())!=null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        is.close();
        isr.close();
        fr.close();
        bw.close();
    }
    //我们看到上边的代码,会有这么几个疑问,1开了这么多流,四次关闭流,麻烦,2,窗口输入也没有一个判断什么时候终止
    public static void test2() throws IOException{
        //创建字节流转换为字符缓冲流的流
        //InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new FileWriter("abc.txt"));
        String line = null;
        while ((line = br.readLine())!= null) {
            if ("911".equals(line)) {
                break;
            } else {
                bw.write(line);
                bw.newLine();
                bw.flush();
            }
        }
        //关闭流
        br.close();
        bw.close();
    }
}
package IO.outputStreamWriter;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;

/*
 * OutputStreamWriter 是字符流通向字节流的桥梁
 * 
 * 把 abc.txt 内容 读取出来, 输出(使用转换流)
 * 
 * 数据源
 *          FileInputStreamDemo.java -- 输入流 -- BufferedReader
 *          br.readLine();
 * 目的地:
 *                      字符流            <-- 把字节流转换成字符流       <-- 字节流            <-- 控制台输出打印
 *          BufferedWriter <-- OutputStreamWriter <-- OutputStream <-- System.out
 *             
 *          bw.write(line);
 *          bw.newLine();
 *          bw.flush();
 * 
 * 使用上 与  理解上的区别?
 *         
 *         理解上:  字符流  --> 字节流
 *         使用上:  字符流 <-- 字节流
 *     
 */
public class OutputStreamWriterDemo {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        test();
        
    }
    public static void test() throws IOException{
        //目的源   字符缓冲流对象
        BufferedReader br = new BufferedReader(new FileReader("abc.txt"));
        //字符流            <-- 把字节流转换成字符流       <-- 字节流            <-- 控制台输出打印
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        String line = null;
        char[] ch = new char[1024];
        while ((line = br.readLine())!=null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        //关闭流
        br.close();
        bw.close();
    }
}

10.5 编码

package encode;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;

public class EncodeDemo {

    public static void main(String[] args) throws IOException {
        //IO流的编码
        encodeIO();
        //字符串编码
        encodeString();
        
    }
    /*
     * IO流的编码
     * 需求: 
     *         1、使用gbk编码表 将数据写入到demo.txt 文件中
     *         2、使用gbk编码表,将demo.txt文件中的数据获取出来
     * 编码:
     * OutputStreamWriter(字符-->字节)
     *         public OutputStreamWriter(OutputStream out,Charset cs)
     * 解码:
     * InputStreamReader(字节--> 字符)
     *         public InputStreamReader(InputStream in,Charset cs)
     */
    public static void encodeIO() throws IOException{
        //解码操作---看得懂的转为看不懂的字节码
        InputStreamReader fis = new InputStreamReader(new FileInputStream("demo.java"),"gbk");
        //编码操作---把看不懂的字节码按照编码规则编为看得懂的字符
        OutputStreamWriter fos = new OutputStreamWriter(new FileOutputStream("demo.txt"),"utf-8");
        int len = 0;
        char[] ch = new char[1024];
        while ((len = fis.read(ch))!= -1) {
            System.out.println(String.valueOf(ch, 0, len));
            fos.write(ch, 0, len);
        }
        fis.close();
        fos.close();
    }
    /*
     * 字符编码
     * 编码: 把能看懂的,变成看不懂的
     * 解码:把看不懂, 变成看懂的
     * 常见的编码表:
     *         ASCII码表: 用7位字节来存储数据
     *         ISO-8859-1: 西欧编码,用8位字节来存储数据
     *         GB2312: 简体中文
     *         GBK:
     *         GB18030:
     *         BIG5: *,繁体中文
     *         Unicode: 统一码
     *             utf-8: 用1-4字节来存储数据的,具体每个数据使用1、2、3、4个字节的哪一个,要看国家区域来决定
     * 编码:
     *         public byte[] getBytes(Charset charset): 使用给定的编码表 进行编码
     * 解码:
     *         public String(byte[] bytes, Charset charset): 使用给定的编码表,进行解码
     * 注意事项:
     *         编码与解码操作,使用的编码表要求统一
     */
    public static void encodeString(){
        //创建字符串,用于作为字符编码的模板
        String str = "我是一个兵,保卫老百姓!";
        try {
            //使用给定的格式进行编码,看懂的编程看不懂得了
            byte[] b = str.getBytes("utf-8");
            //编码上下要一致,否则会出现乱码
            System.out.println("使用该定的编码表进行解码(看不懂的变成看懂的了):"+new String(b,"utf-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
}

10.6 文档复制粘贴

单层文档复制

package IO.practice;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/*
 * 复制 单层文件夹
 * 
 * 需求: 把F:IOio文件夹 复制到 项目的跟目录  copy文件夹
 * 
 * 数据源:F:IOio -- 字节流 -- 字节输入流 -- FileInputStream -- BufferedInputStream
 *          
 * 目的地: copy -- 字节流 -- 字节输出流 -- FileOutputStream -- BufferedOutputStream
 * 
 * 思路:
 *     a:封装数据源
 *     b:创建目的地文件夹,封装目的地
 *     c:获取 数据源 中所有File对象
 *  d:遍历,获取到每一个File对象
 *  e:复制
 *      设置新文件路径
 *      复制文件
 */
public class CopyDirectory {

    public static void main(String[] args) {
        //复制单层目录下的文件
        fileTest();

    }
    //封装数据源,得到每一个file文件
    public static void fileTest(){
        //封装数据源目录对象
        File file = new File("F:\IO\io");
        //封装目的地目录对象,创建目的地文件
        File file1 = new File("copy");
        file1.mkdir();
        //获取源目录
        File[] ff = file.listFiles();
        //遍历每个文件,获取目的地文件
        for (File file2 : ff) {
            //目的地文件名封装对象
            String name = file2.getName();
//            System.out.println(name);
            File dest = new File(file1, name);
            //复制文件,两个参数,一个是源文件,一个是目的地文件
            try {
                copyFile(file2, dest);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
            
    }
    //复制文件,两个参数,一个是源目录封装对象,一个是目的地文件封装对象
    public static void copyFile(File srcFile,File destFile) throws IOException{
        //因为不知道要复制的是文本还是其他,所以选择字节缓冲流
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));
        //设置byte数组作为每次读取字节的长度
        byte[] b = new byte[1024];
        int len = 0;
        //读写操作
        while ((len = bis.read(b))!= -1) {
            bos.write(b, 0, len);
        }
        //关闭流,释放资源
        bis.close();
        bos.close();
        System.out.println("复制完毕!");
    }
}

多层文档复制

package IO.practice;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/*
 * 复制  多层文件夹
 * 
 * 把 E:\day20副本 所有内容  复制到  项目根目录  副本  文件夹中
 * 
 * 数据源:E:\day20副本
 * 
 * 目的地: 副本
 * 
 * 思路:
 *         1、封装数据源
 *         2、封装目的地
 *         3、创建目的地文件夹
 *         4、获取数据源中所有File对象
 *         5、遍历,获取到每一个File对象
 *         6、判断File对象 是否为 文件夹
 *             是:    
 *                 递归,调用本方法,回到第3步
 *             否:
 *                 封装新文件的路径
 *                 复制文件    
 */
public class CopyDirectories {

    public static void main(String[] args) {
        //封装源路径对象    目的地父文档
        File srcFile = new File("F:\IO");
        File dest = new File("copyIO");
        //复制文件夹
        try {
            copyDirectory(srcFile, dest);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    //f封装源路径对象,目的地路径对象
    public static void copyDirectory(File srcFile, File dest) throws IOException{
        //创建目的地父文档
        dest.mkdir();
        //遍历源路径目录
        File[] file = srcFile.listFiles();
        for (File file2 : file) {
            //获取名称
            String name = file2.getName();
            //目的地文件或文件夹
            File destFile = new File(dest, name);
            //判断是否为文件夹
            if(file2.isDirectory()){
                //如果是文件夹,那么递归调用,创建文件夹            
                //复制文件夹,源文件夹file2,目的地文件夹destFile
                copyDirectory(file2, destFile);
                //如果不是文件夹,执行复制,两个参数,源文件,目的地文件
            }else {
                //封装目的地文件新路径
                copyFile(file2,destFile);
            }
        }
    }
    //复制文件,两个参数,一个是源目录封装对象,一个是目的地文件封装对象
    public static void copyFile(File srcFile,File destFile) throws IOException{
        //因为不知道要复制的是文本还是其他,所以选择字节缓冲流
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));
        //设置byte数组作为每次读取字节的长度
        byte[] b = new byte[1024];
        int len = 0;
        //读写操作
        while ((len = bis.read(b))!= -1) {
            bos.write(b, 0, len);
        }
        //关闭流,释放资源
        bis.close();
        bos.close();
        System.out.println("复制完毕!");
    }

}

10.7 集合和文件之间的转换

package IO.listAndFile;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import IO.Student;

/*
 * 把文件中的数据 读取出来, 存储集合中
 * 数据源:文件  bw.txt
 * 目的地:集合
 * 思路:
 *         封装数据源  
 *         创建集合对象
 *         读取数据源中的数据
 *         把数据存储到集合
 * 
 * 把集合中的数据 写入到文件
 * 数据源:集合
 * 目的地:文件
 * 思路:
 *         创建集合对象
 *         添加元素到集合
 *         创建目的地(File)
 *         把集合中的数据  写入到 文件
 */
public class ListAndFileChange {

    public static void main(String[] args) {
        //文件转变为集合
        try {
            FileToList();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //集合转变为文件
        try {
            listToFile();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //集合中存放对象,存放到文件中的是对象的地址
        try {
            ListObjectToFile();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
    //文件转变为集合
    public static void FileToList() throws IOException{
        //封装数据源对象
        File srcFile = new File("demo.txt");
        //创建集合对象,作为文件存储的集合
        List<String> list = new ArrayList<>();
        //创建字节输入流,我们要考虑编码,所以字节更容易控制
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
        //创建字符输入缓冲流,读取文件
//        BufferedReader br = new BufferedReader(new FileReader(srcFile));
        String line = null;
        int len = 0;
        byte[] b = new byte[1024];
        while ((len = bis.read(b))!=-1) {
            String str = new String(b, "utf-8");
            list.add(str);
        }
        //关闭流,释放资源
        bis.close();
        arrayListItrator(list);
    }
    //集合转变为文件,这里使用字节缓存流,可以使用字符缓冲流
    public static void listToFile() throws IOException{
        //创建集合作为源文件
        List<String> list = new ArrayList<>();
        list.add("张三");
        list.add("李四");
        list.add("王二麻子");
        //创建目的地文件,作为写入
        File destFile = new File("abc.txt");
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));
        Iterator<String> iter = list.iterator();
        for (String string : list) {
            byte[] b = string.getBytes();
            bos.write(b);
        }
        bos.close();
    }
    //如果集合中存储的是对象,那么会在文件中存储什么呢
    public static void ListObjectToFile() throws IOException{
        //创建集合作为源文件
        List<Student> list = new ArrayList<>();
        Student s1 = new Student(17, "王五");
        Student s2 = new Student(16, "张三");
        list.add(s1);
        list.add(s2);
        //创建目的地文件,作为写入
        File destFile = new File("abc.txt");
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));
        Iterator<Student> iter = list.iterator();
        for (Student stu : list) {
            byte[] b = stu.toString().getBytes();
            bos.write(b);
        }
        bos.close();
    }
    
    //遍历集合
    public static void arrayListItrator(List<String> list){
        Iterator<String> iter = list.iterator();
        for (String string : list) {
            System.out.println("集合中的元素:"+string);
        }
    }
}

10.8 打印流

package IO.print;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class PrintWriterDemo {

    public static void main(String[] args) {
        //打印流   字符流
        try {
            printTest();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //打印流  方法
        try {
            printMethod();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //打印流  println
        try {
            printlnMethodAndAutoFlush();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //复制指定源文件到目的地文件
        try {
            printWriterDemo();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
    /*
     * 打印流
     * PrintWriter: 字符打印输出流
     * PrintStream: 字节打印输出流
     * 把数据写到如文件
     */
    public static void printTest() throws IOException{
        //创建字符打印输出流
        PrintWriter pw = new PrintWriter("abc.txt");
        //写入
        pw.write("PrintWriter: 字符打印输出流");
        pw.write("
");
        pw.write("PrintWriter: 字符打印输出流");
        //释放资源
        pw.close();
    }
    /*
     * 打印流的特有方法
     *         print() 可以打印各种数据类型的数据
     */
    public static void printMethod() throws IOException{
        //创建字符打印输出流
        PrintWriter pw = new PrintWriter("abc.txt");
        //写入
        pw.write("PrintWriter: 字符打印输出流");
        pw.write("
");
        pw.write("PrintWriter: 字符打印输出流");
        //打印到目的地文件,
        pw.print('a');
        pw.write("
");
        pw.print("我想你了!");
//        pw.flush();  close()实现了刷新流操作,可以省略
        //释放资源
        pw.close();
    }
    /*
     * public void println() : 把各种数据类型的数据打印, 实现换行功能
     * 如果启用了自动刷新,则只有在调用 println 数据自动写入到文件中
     * 
     * 通过构造函数来完成自动刷新
     * public PrintWriter(OutputStream out,boolean autoFlush)
     * public PrintWriter(Writer out, boolean autoFlush)
     */
    public static void printlnMethodAndAutoFlush() throws IOException{
        PrintWriter pw = new PrintWriter(new FileWriter("abc.txt"), true);
        pw.write("我是中国人!");
        pw.print("我是中国人!");
        //只有println配合构造函数的自动刷新才会起作用,println会把前面的也flush了.writer()和print()不会自动把内容刷新到目的地
        pw.println("我是中国人!");
        pw.println("我是中国人!");
        pw.close();
    }
    /*
     * 需求:把F:\Demo.java 文件  复制  到 项目的根目录下 Copy.java  (使用打印流)
     * 
     * 数据源:    E:\Demo.java -- 字符输入流 -- FileReader -- BufferedReader
     * 
     * 目的地:Copy.java -- 字符输出流 -- FileWriter -- BufferedWriter -- PrintWriter
     * 
     * 思路:
     *         a:封装数据源
     *         b:封装目的地
     *         c:读写操作
     *         d:释放资源
     */
    public static void printWriterDemo() throws IOException{
        //创建字符输入缓冲流和打印流  封装数据源和目的地文件
        BufferedReader br = new BufferedReader(new FileReader("F:\Demo.java"));
        PrintWriter pw = new PrintWriter(new FileWriter("Copy.java"), true);
        String str = null;
        while ((str = br.readLine())!= null) {
            pw.println(str);
        }
        br.close();
        pw.close();
    }
}

 10.8.1 printf方法

/*
     * public PrintWriter printf(String format, Object... args):按照指定的格式 进行数据的输出打印
     */
    public static void test(){
        System.out.printf("%B",true);
        System.out.printf("%s","dsadsaeds");
        int x = 20;
        int y = 20;
        System.out.printf("%d+%d=%d",x,y,x+y);
        
    }

10.输入输出
10.1 File(目录和文件路径名的抽象表达形式)
10.2 字符流
10.3 字节流
10.4 缓冲流
10.5 编码
10.6 文档复制粘贴
10.7 集合和文件之间的转换
10.8 打印流
10.9 可变参数
10.10 数组转变为List集合
10.11 Properties
10.12 序列化流&&反序列化流

10.9 可变参数

package args;
/*
 * 可变参数
 *         格式:
 *         修饰符 返回值类型 方法名(数据类型... 变量){
 *         }
 *         变量: 其实 它是数据类型数据的数组
 * 
 *         注意事项: 当使用可变参数的时候, 可变参数必须要在参数列表的最后一个位置
 */
public class ArgsDemo {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ArgsDemo ad = new ArgsDemo();
        test(1,2,3,4);
        System.out.println(ad.test('a',2));
        ad.test(1, 2);
        ad.test(1, 2, 3);
        
    }
    //可变参数---可以考虑方法重载,可变参数意味着,当我们不确定参数个数时使用
    public static void test(int... i){
        for (int j : i) {
            System.out.print(j+" ");
        }
    }
    //方法重载
    public void test(int a,int b){
        System.out.println(a+b);
    }
    //方法的重载注意两点,方法名相同,参数类型或者参数个数不同,其他的不在方法重载的判别范围内(如返回值等)
    public int test(char a,int b){
        return a+b;
    }
    public void test(int a,int b,int c){
        System.out.println(a+b+c);
    }
    
}

10.输入输出
10.1 File(目录和文件路径名的抽象表达形式)
10.2 字符流
10.3 字节流
10.4 缓冲流
10.5 编码
10.6 文档复制粘贴
10.7 集合和文件之间的转换
10.8 打印流
10.9 可变参数
10.10 数组转变为List集合
10.11 Properties
10.12 序列化流&&反序列化流

10.10 数组转变为List集合

package Arrays;

import java.util.Arrays;
import java.util.List;

/*
 * Arrays:数组工具类中的方法
 *         public static <T> List<T> asList(T... a)
 *         把数组 转换为List集合
 */
public class ArrayToList {

    public static void main(String[] args) {
        arrayToListDemo();

    }
    //把数组转变为集合
    public static void arrayToListDemo(){
        //创建Integer类型数组
        Integer[] i = new Integer[]{1,2,3,4,5};
        //将数组作为可变参数传入,方法,转变为List集合
        List<Integer> list = Arrays.asList(i);
        for (Integer in : list) {
            System.out.println(in);
        }
    }
}

10.输入输出
10.1 File(目录和文件路径名的抽象表达形式)
10.2 字符流
10.3 字节流
10.4 缓冲流
10.5 编码
10.6 文档复制粘贴
10.7 集合和文件之间的转换
10.8 打印流
10.9 可变参数
10.10 数组转变为List集合
10.11 Properties
10.12 序列化流&&反序列化流

10.11 Properties

package properties;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Properties;
import java.util.Set;

public class PropertiesDemo {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
//        propertiesTest();
//        propertiesMethod();
//        propertiesFunction();
//        propertiesLoadTest();
        propertiesDemo();
    }
    /*
     * Properties
     * 是一个集合与IO流相互处理的类
     * 通过观察,Properties它的父类 是Hashtable类,所以,它是Map集合
     * 属性列表中每个键及其对应值都是一个字符串
     */
    public static void propertiesTest(){
        Properties p = new Properties();
        p.put("及时雨", "宋公明");
        p.put("玉麒麟", "卢俊义");
        p.put("智多星", "吴用");
        System.out.println("通过键获取值:"+p.get("智多星"));
    }
    /*
     * Properties的特有方法
     *         添加功能:
     *             public Object setProperty(String key, String value) 调用 Hashtable 的方法 put
     *         获取功能:
     *             public String getProperty(String key) : 返回给定的key 对应的值
     *             public String getProperty(String key, String defaultValue) 
     *                     返回给定的key 对应的值, 如果该键不存在,返回 defaultValue
     *                 
     *             public Set<String> stringPropertyNames() 返回键的集合
     */
    public static void propertiesMethod(){
        Properties p = new Properties();
        p.setProperty("及时雨", "宋公明");
        p.setProperty("玉麒麟", "卢俊义");
        p.setProperty("智多星", "吴用");
        System.out.println("通过指定的键获取值,如果值不存在返回null:"+p.getProperty("黑旋风"));
        System.out.println("通过指定的键获取值,如果值不存在返回null:"+p.getProperty("及时雨"));
        System.out.println("返回给定的key 对应的值, 如果该键不存在,返回 defaultValue:"+p.getProperty("黑旋风", "是李逵"));
        System.out.println("返回给定的key 对应的值, 如果该键不存在,返回 defaultValue:"+p.getProperty("及时雨", "是李逵"));
        Set<String> s = p.stringPropertyNames();
        for (String string : s) {
            System.out.println("键:"+string);
        }
    }
    /*
     * Properties特有方法
     *         public void list(PrintStream out) : 把集合数据 写入到指定的文件中
     *         public void list(PrintWriter out) :  把集合数据 写入到指定的文件中
     * 
     *  我想把集合中的数据  写入到文件
     *  
     *  思路:
     *      a:集合
     *      b:添加数据
     *      c:封装目的地   prop.txt
     *      d:把集合中的数据写入目的地 文件
     */
    public static void propertiesFunction() throws IOException{
        //集合
        Properties p = new Properties();
        p.setProperty("及时雨", "宋公明");
        p.setProperty("玉麒麟", "卢俊义");
        p.setProperty("智多星", "吴用");
        //目的地封装文件
        PrintWriter pw = new PrintWriter("p.properties");
        //把集合写入到文件
        p.list(pw);
        //关闭流
        pw.close();
    }
    /*
     * Properties特有方法
     *         public void load(InputStream inStream)
     *         public void load(Reader reader)
     * 
     * 需求: 把文件中的数据获取出来, 存入集合  (这个文件中的数据要是必须是键值对格式)
     * 思路:
     *         a: 创建集合
     *         b: 封装数据源 prop.txt
     *         c: 获取数据到集合
     */
    public static void propertiesLoadTest() throws IOException{
        Properties p = new Properties();
        System.out.println("P:"+p);
        FileReader fr = new FileReader("abc.txt");
        p.load(fr);
        System.out.println("p:"+p);
        Set<String> s = p.stringPropertyNames();
        for (String string : s) {
            System.out.println(string);
            System.out.println(p.getProperty(string));
        }
    }
    /*
     * Properties特有方法
     *         public void store(OutputStream out, String comments)
     *         public void store(Writer writer, String comments)
     * 参数2是 属性列表的描述
     * 把集合数据 存入到文件中
     */
    public static void propertiesDemo() throws IOException{
        Properties p = new Properties();
        p.setProperty("及时雨", "宋公明");
        p.setProperty("玉麒麟", "卢俊义");
        p.setProperty("智多星", "吴用");
        //目的地封装文件
        PrintWriter pw = new PrintWriter("pp.properties");
        p.store(pw, "what is this!");
    }
    
}

通过键获取值:吴用
通过指定的键获取值,如果值不存在返回null:null
通过指定的键获取值,如果值不存在返回null:宋公明
返回给定的key 对应的值, 如果该键不存在,返回 defaultValue:是李逵
返回给定的key 对应的值, 如果该键不存在,返回 defaultValue:宋公明
键:及时雨
键:玉麒麟
键:智多星
P:{}
p:{我是中国人!我是中国人!我是中国人!=, 我是中国人!=}
我是中国人!我是中国人!我是中国人!

我是中国人!

package properties;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Properties;
import java.util.Set;

/*
 * 需求: 读取user.txt中的数据 (一个键值对形式内容,  键是名称,  值是年龄)  
 *         如果有"lisi"这个人,把这个人的年龄 更给为100
 *         重新存储起来
 * 
 * 
 * 思路:
 *         a:读取user.txt文件, 读取到Properties集合中
 *         b: 获取所有的键
 *         c: 遍历,得到每一个键
 *         d: 判断键是否是"lisi"
 *             是:给"lisi"的值 更新为100
 *             否:不管了
 */
public class PropertiesTest {

    public static void main(String[] args) throws IOException {
        //创建集合对象
        Properties p = new Properties();
        //常见源文件对象,封装文件
        FileReader fr = new FileReader("user.txt");
        //把文件写入集合
        p.load(fr);
        //获取所有键
        Set<String> s = p.stringPropertyNames();
        System.out.println(p.get("李四"));
        //遍历键
        for (String string : s) {
            //判断
            if(string.equals("李四")){
                p.setProperty(string, "100");
            }
        }
        System.out.println(p.get("李四"));
        //把集合中元素,写入文件
        p.list(new PrintStream("user.txt"));
        fr.close();
    }

}

 10.输入输出
10.1 File(目录和文件路径名的抽象表达形式)
10.2 字符流
10.3 字节流
10.4 缓冲流
10.5 编码
10.6 文档复制粘贴
10.7 集合和文件之间的转换
10.8 打印流
10.9 可变参数
10.10 数组转变为List集合
10.11 Properties
10.12 序列化流&&反序列化流

10.12 序列化流&&反序列化流

package Serializable;

import java.io.Serializable;

/*java.io.NotSerializableException: Serializable.Person
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1183)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347)
    at Serializable.ObjectOutputSreamDemo.test1(ObjectOutputSreamDemo.java:40)
    at Serializable.ObjectOutputSreamDemo.main(ObjectOutputSreamDemo.java:25)
 * * 当实例需要具有序列化接口时,抛出此异常
 * 没有实现序列化接口
 * java.io.NotSerializableException
 * 
 * Serializable:序列化接口
 * 类通过实现 java.io.Serializable 接口以启用其序列化功能
 * 
 * */
public class Person implements Serializable{
    public String name;
    public int age;
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public Person() {
        super();
        // TODO Auto-generated constructor stub
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    
}
package Serializable;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/*
 *  序列化流:
 *  ObjectOutputStream : 把对象  以流的方式操作
 *  ObjectOutputStream : 将 Java 对象的基本数据类型和图形写入 OutputStream
 *      方法:
 *      public final void writeObject(Object obj): 将指定的对象写入 ObjectOutputStream
 *  
 *  反序列化流:
 *  ObjectInputStream: 把流对象 解析成 对象使用
 *  
 *  把person 对象 写入 demo.txt中
 */
public class ObjectOutputSreamDemo {

    public static void main(String[] args) throws ClassNotFoundException, IOException {
        //序列化流
        try {
            test1();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //反序列化流
        test2();
    }
    //把对象写入流
    public static void test1() throws IOException{
        //常见序列化流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
        //创建自定义对象
        Person p = new Person("游先生",27);
        //把对象写入流,网络上传输都是字节流
        //把自定义对象 写入流中,就相当于 写入到文件中
        oos.writeObject(p);
        //关闭流
        oos.close();
    }
    //把流中的对象解析出来
    public static void test2() throws IOException,ClassNotFoundException{
        //创建反序列化流
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txt"));
        //把反序列化流写出
        Object object = ois.readObject();
        Person p = (Person) object;
        System.out.println(p.getName()+"  "+p.getAge());
        //关闭流
        ois.close();
    }
}

10.输入输出
10.1 File(目录和文件路径名的抽象表达形式)
10.2 字符流
10.3 字节流
10.4 缓冲流
10.5 编码
10.6 文档复制粘贴
10.7 集合和文件之间的转换
10.8 打印流
10.9 可变参数
10.10 数组转变为List集合
10.11 Properties
10.12 序列化流&&反序列化流