package com.sf.iotest;

import org.junit.Test;

import java.io.*;
import java.util.*;

public class test01 {
    public static void main(String[] args) {
        String pathname = "c:\\aaa.txt";
        File file = new File(pathname);

        // 文件路径名
        String pathname2 = "D:\\aaa\\bbb.txt";
        File file2 = new File(pathname2);

        // 通过父路径和子路径字符串
        String parent = "d:\\aaa";
        String child = "bbb.txt";
        File file3 = new File(parent, child);

        // 通过父级File对象和子路径字符串
        File parentDir = new File("d:\\aaa");
        String childFile = "bbb.txt";
        File file4 = new File(parentDir, childFile);
    }

    @Test
    public void t2(){
        File f1 = new File("d:\\a.txt");
        System.out.println("文件/目录的名称：" + f1.getName());
        System.out.println("文件/目录的构造路径名：" + f1.getPath());
        System.out.println("文件/目录的绝对路径名：" + f1.getAbsolutePath());
        System.out.println("文件/目录的父目录名：" + f1.getParent());
    }

    @Test
    public void t3(){
        File f3 = new File("a.txt");
        System.out.println("user.dir =" + System.getProperty("user.dir"));
        System.out.println("文件/目录的名称：" + f3.getName());
        System.out.println("文件/目录的构造路径名：" + f3.getPath());
        System.out.println("文件/目录的绝对路径名：" + f3.getAbsolutePath());
        System.out.println("文件/目录的父目录名：" + f3.getParent());
    }

    @Test
    public void t4(){
        File f = new File("d:/aaa/bbb.txt");
        System.out.println("文件构造路径:"+f.getPath());
        System.out.println("文件名称:"+f.getName());
        System.out.println("文件长度:"+f.length()+"字节");
        System.out.println("文件最后修改时间：" + f.lastModified());

        File f2 = new File("d:/aaa");
        System.out.println("目录构造路径:"+f2.getPath());
        System.out.println("目录名称:"+f2.getName());
        System.out.println("目录长度:"+f2.length()+"字节");
        System.out.println("文件最后修改时间：" + new Date(f.lastModified()));
    }

    @Test
    public void t5(){
        File dir = new File("d:/ruanjian");
        String[] subs = dir.list();
        System.out.println(Arrays.toString(subs));
        for (String sub : subs) {
            System.out.println(sub);
        }
    }

    @Test
    public void t6(){
        File file1 = new File("d:/a.txt");
        File file2 = new File("d:/b.txt");
        System.out.println(file1.getName());
        boolean b = file1.renameTo(file2);
        System.out.println(b);
    }

    @Test
    public void t7(){
        File f = new File("d:\\a.txt");
        File f2 = new File("d:\\tmp");
        // 判断是否存在
        System.out.println("d:\\aaa\\bbb.java 是否存在:"+f.exists());
        System.out.println("d:\\aaa 是否存在:"+f2.exists());
        // 判断是文件还是目录
        System.out.println("d:\\aaa 文件?:"+f2.isFile());
        System.out.println("d:\\aaa 目录?:"+f2.isDirectory());
    }

    @Test
    public void t8() throws IOException {
        // 文件的创建
        File f = new File("aaa.txt");
        System.out.println("aaa.txt是否存在:"+f.exists());
        System.out.println("aaa.txt是否创建:"+f.createNewFile());
        System.out.println("aaa.txt是否存在:"+f.exists());

        // 目录的创建
        File f2= new File("newDir");
        System.out.println("newDir是否存在:"+f2.exists());
        System.out.println("newDir是否创建:"+f2.mkdir());
        System.out.println("newDir是否存在:"+f2.exists());

        // 创建一级目录
        File f3= new File("newDira\\newDirb");
        System.out.println("newDira\\newDirb创建：" + f3.mkdir());
        File f4= new File("newDir\\newDirb");
        System.out.println("newDir\\newDirb创建：" + f4.mkdir());
        // 创建多级目录
        File f5= new File("newDira\\newDirb");
        System.out.println("newDira\\newDirb创建：" + f5.mkdirs());

        // 文件的删除
        System.out.println("aaa.txt删除：" + f.delete());

        // 目录的删除
        System.out.println("newDir删除：" + f2.delete());
        System.out.println("newDir\\newDirb删除：" + f4.delete());
    }

    @Test
    public void t9() throws IOException {
        //利用File构造器，new一个文件目录file
        // 在其中创建 当前日期目录 之后创建helloworld.java文件
        //编写方法，实现删除file中指定文件的操作
        File file = new File("D:\\file");
        boolean mkdirs = file.mkdirs();
        if (mkdirs) {
            File file1 = new File("D:\\file\\a.java");
            file1.createNewFile();
        }
    }

    /**
     * 判断指定目录下是否有后缀名为.jpg的文件。如果有，就输出该文件名称
     */
    @Test
    public void t10(){
        File srcFile = new File("d:\\demo");
        String[] fileNames = srcFile.list();
        for(String fileName : fileNames){
            if(fileName.endsWith(".jpg")){
                System.out.println(fileName);
            }
        }
    }

    /**
     * 方法二
     * 判断指定目录下是否有后缀名为.jpg的文件。如果有，就输出该文件名称
     */
    @Test
    public void t11(){
        File srcFile = new File("d:\\demo");
        File[] listFiles = srcFile.listFiles();
        for(File file : listFiles){
            if(file.getName().endsWith(".jpg")){
                System.out.println(file.getAbsolutePath());
            }
        }
    }

    /**
     *判断指定目录下是否有后缀名为.jpg的文件。如果有，就输出该文件名称
     * * File类提供了两个文件过滤器方法
     * 	 * public String[] list(FilenameFilter filter)
     * 	 * public File[] listFiles(FileFilter filter)
     */
    @Test
    public void t12(){
        File file = new File("d:\\demo");
        File[] files = file.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.endsWith(".jsp");
            }
        });
        for (File file1 : files) {
            System.out.println(file1.getAbsolutePath());
        }
    }

    /**
     * 练习3：遍历指定目录所有文件名称，包括子文件目录中的文件。
     *  拓展1：并计算指定目录占用空间的大小
     *  拓展2：删除指定文件目录及其下的所有文件
     */
    @Test
    public void t13(){
        /**
         * 代码在另外一个类（ListFilesTest）中的主函数中
         */
    }

    /**
     * 读取hello.txt文件中的字符数据，并显示在控制台上
     */
    @Test
    public void t14() throws IOException {
        // 1、创建file类的对象  对应着物理磁盘上的某个文件
        File file = new File("d:\\a.txt");
        //2 、创建fileReader对象  将file类的对象作为参数传递到fileRead的构造器中
        FileReader fr = new FileReader(file);
        //3、通过相关流的方法  读取文件中的数据
        int data;
        while ((data = fr.read()) !=-1){
            System.out.println((char) data);
        }
        //4、关闭相关的流资源  避免出现内存泄露
        fr.close();
    }


    /**
     * 实现方法3  调用read(char[] cbuf),每次从文件中读取多个字符     FileReader --read()
     * @throws IOException
     */
    @Test
    public void t15() throws IOException {
        FileReader fr = null;
        try {
            //1. 创建File类的对象，对应着物理磁盘上的某个文件
            File file = new File("d:\\a.txt");
            //2. 创建FileReader流对象，将File类的对象作为参数传递到FileReader的构造器中
            fr = new FileReader(file);
            //3. 通过相关流的方法，读取文件中的数据
            char[] cbuf = new char[5];
            /*
             * read(char[] cbuf) : 每次将文件中的数据读入到cbuf数组中，并返回读入到数组中的
             * 字符的个数。
             * */
            int len; //记录每次读入的字符的个数
            while ((len = fr.read(cbuf)) != -1) {
                //处理char[]数组即可
                //正确：
                String str = new String(cbuf, 0, len);
                System.out.print(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4. 关闭相关的流资源，避免出现内存泄漏
            if (fr != null)
                fr.close();
        }
    }

    @Test
    public void t16() throws IOException {
        // 使用文件名称创建流对象
        FileWriter fw = new FileWriter(new File("d:\\fw.txt"));
        // 写出数据
        fw.write(97); // 写出第1个字符
        fw.write('b'); // 写出第2个字符
        fw.write('C'); // 写出第3个字符
        fw.write(30000); // 写出第4个字符，中文编码表中30000对应一个汉字。
        //关闭资源
        fw.close();
    }

    @Test
    public void t17() throws IOException {
        // 使用文件名称创建流对象
        FileWriter fw = new FileWriter(new File("fw.txt"));
        // 字符串转换为字节数组
        char[] chars = "爱扣钉".toCharArray();
        // 写出字符数组
        fw.write(chars); // 爱扣钉
        // 写出从索引1开始，2个字符。
        fw.write(chars,1,2); // 钉钉
        // 关闭资源
        fw.close();
    }

    @Test
    public void t18() throws IOException {
        FileWriter fw = null;
        try {
            //1. 创建File的对象
            File file = new File("personinfo.txt");
            //2. 创建FileWriter的对象，将File对象作为参数传递到FileWriter的构造器中
            //如果输出的文件已存在，则会对现有的文件进行覆盖
            fw = new FileWriter(file);
//            fw = new FileWriter(file,false);
            //如果输出的文件已存在，则会在现有的文件末尾写入数据
//            fw = new FileWriter(file,true);

            //3. 调用相关的方法，实现数据的写出操作
            //write(String str) / write(char[] cbuf)
            fw.write("hello world");
            fw.write("world".toCharArray());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4. 关闭资源，避免内存泄漏
            try {
                if (fw != null)
                    fw.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    @Test
    public void t19() throws IOException {
//复制文件  b.txt  到 upload下
        FileReader fr = new FileReader("d:\\a.txt");
        FileWriter fw = new FileWriter("d:\\b.txt",true);
        //数组
        char[] chars = new char[1024*8];

        int len;
        while (  (len=fr.read(chars)) != -1 ){
            fw.write(chars,0,len);
        }

        //关闭
        fw.close();
        fr.close();
    }

    @Test
    public void t20() throws IOException {
        // 使用文件名称创建流对象
        FileWriter fw = new FileWriter("fw.txt");
        // 写出数据，通过flush
        fw.write('刷'); // 写出第1个字符
        fw.flush();
        fw.write('新'); // 继续写出第2个字符，写出成功
        fw.flush();

        // 写出数据，通过close
        fw.write('关'); // 写出第1个字符
        fw.close();
        fw.write('闭'); // 继续写出第2个字符,【报错】java.io.IOException: Stream closed
        fw.close();
    }

    @Test
    public void t21() throws IOException {
        // 使用文件名称创建流对象
        FileInputStream fis = new FileInputStream("D:\\a.txt");
        // 读取数据，返回一个字节
        int read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        // 读取到末尾,返回-1
        read = fis.read();
        System.out.println(read);
        // 关闭资源
        fis.close();
    }

    @Test
    public void t22() throws IOException {
        // 使用文件名称创建流对象
        FileInputStream fis = new FileInputStream("D:\\a.txt");
        // 定义变量，保存数据
        int b;
        // 循环读取
        while ((b = fis.read())!=-1) {
            System.out.println((char)b);
        }
        // 关闭资源
        fis.close();
    }
    @Test
    public void t23()throws IOException{
        // 使用文件名称创建流对象.
        FileInputStream fis = new FileInputStream("D:\\a.txt"); // 文件中为abcde
        // 定义变量，作为有效个数
        int len;
        // 定义字节数组，作为装字节数据的容器
        byte[] b = new byte[2];
        // 循环读取
        while (( len= fis.read(b))!=-1) {
            // 每次读取后,把数组变成字符串打印
            System.out.println(new String(b));
        }
        // 关闭资源
        fis.close();
        /*
        输出结果：
        ab
        cd
        ed
        最后错误数据`d`，是由于最后一次读取时，只读取一个字节`e`，数组中，
        上次读取的数据没有被完全替换，所以要通过`len` ，获取有效的字节
         */
    }

    @Test
    public void t24()throws IOException{
        // 使用文件名称创建流对象.
        FileInputStream fis = new FileInputStream("D:\\a.txt"); // 文件中为abcde
        // 定义变量，作为有效个数
        int len;
        // 定义字节数组，作为装字节数据的容器
        byte[] b = new byte[2];
        // 循环读取
        while (( len= fis.read(b))!=-1) {
            // 每次读取后,把数组的有效字节部分，变成字符串打印
            System.out.println(new String(b,0,len));//  len 每次读取的有效字节个数
        }
        // 关闭资源
        fis.close();
        /*
        输出结果：
        ab
        cd
        e
         */
    }

    @Test
    public void t25() throws IOException {
        // 使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("fos.txt");
        // 写出数据
        fos.write(97); // 写出第1个字节
        fos.write(98); // 写出第2个字节
        fos.write(99); // 写出第3个字节
        // 关闭资源
        fos.close();
        /*  输出结果：abc*/
    }

    @Test
    public void t26() throws IOException {
        // 使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("fos.txt");
        // 字符串转换为字节数组
        byte[] b = "abcde".getBytes();
        // 写出从索引2开始，2个字节。索引2是c，两个字节，也就是cd。
        fos.write(b,2,2);
        // 关闭资源
        fos.close();
    }

    @Test
    public void t27() throws IOException{
        // 使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("fos.txt",true);
        // 字符串转换为字节数组
        byte[] b = "abcde".getBytes();
        fos.write(b);
        // 关闭资源
        fos.close();
    }

    //使用FileInputStream\FileOutputStream，实现对文件的复制
    @Test
    public void test28() {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            //1. 造文件-造流
            //复制图片：成功
//            fis = new FileInputStream(new File("pony.jpg"));
//            fos = new FileOutputStream(new File("pony_copy1.jpg"));

            //复制文本文件：成功
            fis = new FileInputStream(new File("D:\\a.txt"));
            fos = new FileOutputStream(new File("D:\\hello1.txt"));

            //2. 复制操作（读、写）
            byte[] buffer = new byte[1024];
            int len;//每次读入到buffer中字节的个数
            while ((len = fis.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }
            System.out.println("复制成功");
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //3. 关闭资源
            try {
                if (fos != null)
                    fos.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            try {
                if (fis != null)
                    fis.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

    }


    //图片的复制
    @Test
    public void t29() throws Exception {
        FileInputStream fis = new FileInputStream("C:\\Users\\Lenovo\\Desktop\\123.jpg");
        FileOutputStream fos = new FileOutputStream("C:\\Users\\Lenovo\\Desktop\\3.jpg");
        //数组 缓冲
        byte[] bytes = new byte[8192];
        int len;
        //循环读取
        while (  ( len = fis.read(bytes) ) != -1 ){
            //输出
            fos.write(bytes,0,len);
        }

        //关闭
        fos.close();
        fis.close();
    }


    @Test
    public void t30() {
        /*
         * 图片的加密
         * */
            FileInputStream fis = null;
            FileOutputStream fos = null;
            try {
                File file1 = new File("C:\\Users\\Lenovo\\Desktop\\123.jpg");
                File file2 = new File("C:\\Users\\Lenovo\\Desktop\\3.jpg");
                fis = new FileInputStream(file1);
                fos = new FileOutputStream(file2);

                //方式1：每次读入一个字节，效率低
//            int data;
//            while((data = fis.read()) != -1){
//                fos.write(data ^ 5);
//            }
                //方式2：每次读入一个字节数组，效率高
                int len;
                byte[] buffer = new byte[1024];
                while ((len = fis.read(buffer)) != -1) {

                    for (int i = 0; i < len; i++) {
                        buffer[i] = (byte) (buffer[i] ^ 5);
                    }

                    fos.write(buffer, 0, len);

                }


                System.out.println("加密成功");
            } catch (IOException e) {
                e.printStackTrace();
            } finally {

                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }


    /*
     * 图片的解密
     * */
    @Test
    public void t31(){
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            File file1 = new File("C:\\Users\\Lenovo\\Desktop\\3.jpg");
            File file2 = new File("C:\\Users\\Lenovo\\Desktop\\12345.jpg");
            fis = new FileInputStream(file1);
            fos = new FileOutputStream(file2);

            //方式1：每次读入一个字节，效率低
//            int data;
//            while((data = fis.read()) != -1){
//                fos.write(data ^ 5);
//            }
            //方式2：每次读入一个字节数组，效率高
            int len;
            byte[] buffer = new byte[1024];
            while((len = fis.read(buffer)) != -1){

                for(int i = 0;i < len;i++){
                    buffer[i] = (byte) (buffer[i] ^ 5);
                }

                fos.write(buffer,0,len);

            }

            System.out.println("解密成功");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {

            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 缓存流
     */

    public void copyFileWithFileStream(String srcPath,String destPath) throws IOException{
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            //1. 造文件-造流
            fis = new FileInputStream(new File(srcPath));
            fos = new FileOutputStream(new File(destPath));

            //2. 复制操作（读、写）
            byte[] buffer = new byte[100];
            int len;//每次读入到buffer中字节的个数
            while ((len = fis.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }
            System.out.println("复制成功");
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //3. 关闭资源
            fos.close();
            fis.close();
        }
    }

    @Test
    public void t32() throws IOException{
        String srcPath = "D:\\ruanjian\\WeChat\\WeChat.exe";
        String destPath = "D:\\ruanjian\\WeChat\\01_WeChat.exe";

        long start = System.currentTimeMillis();

        copyFileWithFileStream(srcPath,destPath);

        long end = System.currentTimeMillis();

        System.out.println("花费的时间为：" + (end - start));//46毫秒
    }

    //方法2：使用BufferedInputStream\BufferedOuputStream实现非文本文件的复制
    public void copyFileWithBufferedStream(String srcPath,String destPath){
        FileInputStream fis = null;
        FileOutputStream fos = null;
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            //1. 造文件
            File srcFile = new File(srcPath);
            File destFile = new File(destPath);
            //2. 造流
            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);

            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);

            //3. 读写操作
            int len;
            byte[] buffer = new byte[100];
            while ((len = bis.read(buffer)) != -1) {
                bos.write(buffer, 0, len);
            }
            System.out.println("复制成功");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4. 关闭资源(如果有多个流，我们需要先关闭外面的流，再关闭内部的流)
            try {
                if (bos != null)
                    bos.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            try {
                if (bis != null)
                    bis.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

        }
    }
    @Test
    public void t33(){
        String srcPath = "D:\\ruanjian\\WeChat\\WeChat.exe";
        String destPath = "D:\\ruanjian\\WeChat\\01_WeChat.exe";

        long start = System.currentTimeMillis();

        copyFileWithBufferedStream(srcPath,destPath);

        long end = System.currentTimeMillis();

        System.out.println("花费的时间为：" + (end - start));//3毫秒
    }


    /**
     * 字符缓冲流特有方法
     */

    @Test
    public void t34() throws IOException{
        // 创建流对象
        BufferedReader br = new BufferedReader(new FileReader("out.txt"));
        // 定义字符串,保存读取的一行文字
        String line;
        // 循环读取,读取到最后返回null
        while ((line = br.readLine())!=null) {
            System.out.println(line);
        }
        // 释放资源
        br.close();
    }

    @Test
    public void testNewLine() throws IOException{
// 创建流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("out.txt"));
        // 写出数据
        bw.write("爱");
        // 写出换行
        bw.newLine();
        bw.write("扣");
        bw.newLine();
        bw.write("钉");
        bw.newLine();
        // 释放资源
        bw.close();
    }


    @Test
    public void t35() throws IOException{
        //字符
        BufferedReader br = new BufferedReader(new FileReader("out.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("out1.txt"));

        //map集合
        HashMap<String,Integer> map = new HashMap<>();

        String s;
        while ( (s =br.readLine()) != null ){
            //获取 s的第一个字符
            char name = s.charAt(0);

            if (map.containsKey(name)){
                Integer integer = map.get(name);
                integer++;
                //key Steing  value Integer
                map.put(String.valueOf(name),integer);
            }else{
                map.put(String.valueOf(name),1);
            }
        }

        //循环map 输出
        Set<Map.Entry<String, Integer>> entries = map.entrySet();
        //循环输出
        for (Map.Entry<String, Integer> entry : entries) {
            bw.write(entry.getKey()+":"+entry.getValue());
            bw.newLine();
        }

        bw.close();
        br.close();
    }

    /**
     * 使用`FileReader` 读取项目中的文本文件。由于IDEA设置中针对项目设置了UTF-8编码，
     * 当读取Windows系统中创建的文本文件时，如果Windows系统默认的是GBK编码，则读入内存中会出现乱码。
     */
    @Test
    public void t36() throws IOException{
        FileReader fileReader = new FileReader("D:\\File_GBK.txt");
        int data;
        while ((data = fileReader.read()) != -1) {
            System.out.print((char)data);
        }
        fileReader.close();
    }

    /**
     * 序列化和反序列化
     */

    @Test
    public void save() throws IOException {
        String name = "巫师";
        int age = 300;
        char gender = '男';
        int energy = 5000;
        double price = 75.5;
        boolean relive = true;

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("game.dat"));
        oos.writeUTF(name);
        oos.writeInt(age);
        oos.writeChar(gender);
        oos.writeInt(energy);
        oos.writeDouble(price);
        oos.writeBoolean(relive);
        oos.close();
    }

    @Test
    public void reload()throws IOException{
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("game.dat"));
        String name = ois.readUTF();
        int age = ois.readInt();
        char gender = ois.readChar();
        int energy = ois.readInt();
        double price = ois.readDouble();
        boolean relive = ois.readBoolean();

        System.out.println(name+"," + age + "," + gender + "," + energy + "," + price + "," + relive);

        ois.close();
    }
}



