File与IO

作者: Liu积土成山 | 来源:发表于2020-01-22 17:04 被阅读0次

File

File类:表示文件和目录路径名的抽象。
File类可以实现文件的创建、删除、重命名、得到路径、创建时间等等,是唯一与文件本身有关的操作类。

public static final String separator 表示路径分隔符“\”
public File(String pathname) 构造File类实例,传入路径
public boolean createNewFile() 创建新文件
public boolean delete() 删除文件
public boolean isDirectory() 判断给定的路径是否是文件夹
public boolean isFile 判断给定的路径是否是文件
public String[] list() 列出文件夹中的文件
public boolean mkdir() 创建新的文件夹
public boolean renameTo(File dest) 为文件重命名
public long length() 返回文件大小
String getPath() 路径名字符串
public class FileDemo01 {
    public static void main(String[] args) {
        // 表示一个文件或目录,带后缀名的就是文件,不带后缀名是目录
        File file = new File("/Users/liuyan/Documents/ppt/kotlin");
        // 列出当前目录下所有文件名
        String[] fileNames = file.list();
//        System.out.print("当前目录下所有文件名:"+ Arrays.toString(fileNames));
        File[] files = file.listFiles();
        for (File f : files) {
            // f.length 文件的长度 f.getName文件的名字
//            System.out.println("列出当前目录下的所有文件,以file对象返回:"+f);
            System.out.println("相对路径:" + f.getPath());
            System.out.println("绝对路径:" + f.getAbsolutePath());
            System.out.println("是否是隐藏文件:" + f.isHidden());
            System.out.println("是否可读文件:" + f.canRead());
            // 毫秒形式展示
            Date date = new Date(f.lastModified());
            DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
            System.out.println("文件最后修改时间:" + dateFormat.format(date));

            // mkdir 和mkdirs 如果每一及都没有就用mkdirs 只有一层可以用mkdir
            File file1 = new File("/Users/liuyan/IdeaProjects/BiliFengJia/src/mkdir");
            file1.mkdirs();
        }
        System.out.println("----------------------------");
        // 查找目录下以.xlsx结尾的文件
        File[] listFiles = file.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.getName().endsWith(".xlsx");
            }
        });
        for (File f2 : listFiles) {
            System.out.println(f2.getName());
        }

    }
}

/**
 * 在指定的目录中查找文件,查找制定目录下以apk结尾的文件
 */
public class FileDemo02 {
    public static void main(String[] args) {
        File file = new File("/Users/liuyan/Documents/ppt/kotlin");
        findFile(file, ".apk");
    }

    /**
     * 查找文件,原目录,查找的文件
     */
    private static void findFile(File target, String dest) {
        if (target == null) {
            return;
        }
        // 如果文件是目录
        if (target.isDirectory()) {
            // 如果目录里面还有目录,递归
            File[] files = target.listFiles();
            if (files != null) {
                for (File f : files) {
                    findFile(f,dest);
                }
            }
        } else {
            // 不是目录,是文件  // toUpperCase() 全转大写   toLowerCase() 全转小写
            String name = target.getName().toLowerCase();
//            System.out.println("------->>>"+name);
            if(name.endsWith(dest)){
                System.out.println("---"+target.getAbsolutePath());
            }
        }
    }
}

IO

流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。数据在俩设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各个类,更方便直观的进行数据操作。

IO流的分类

根据处理数据类型的不同分为:字符流和字节流
根据数据流向不同分为:输入流和输出流

/**
 * 字节输入输出流
 * 输出流:超类OutputStream,对文件的输出流使用子类FileOutputStream
 * 输入流:超类InputStream,对文件的输入流使用子类FileInputStream
 */
public class ByteStreamDemo {
    public static void main(String[] args) {
        // 输出流
        out();
        // 输入流
        in();
    }

    private static void out() {
        try {
            // 1. 确定目标文件
            File file = new File("/Users/liuyan/IdeaProjects/BiliFengJia/src/a.txt");
            // 2.构建一个文件输出流对象
            OutputStream os = new FileOutputStream(file);
            // 3.输出的内容
            String info = "hello world";
            // 4.把内容写入文件
            os.write(info.getBytes());
            // 5.关闭流
            os.close();
            System.out.println("write success");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void in() {
        try {
            // 1. 确定目标文件
            File file = new File("/Users/liuyan/IdeaProjects/BiliFengJia/src/a.txt");
            FileInputStream in = new FileInputStream(file);
            // 读取,一次读取多大,自己设定一个
            byte[] bytes = new byte[1024];
            StringBuilder sb = new StringBuilder();
            // 每次读取的字节长度 -1表示没有
            int len = -1;
            // 把数据读入到byte数组中,并返回读取的字节数,当不等于-1时,表示读取到数据,等于-1表示文件读完了
            while ((len = in.read(bytes)) != -1) {
                // 根据读取到的字节数组,再转换为字符串内容,添加到StringBuilder中
                // 中文占2个字节,有可能读到中文的一半,会出现乱码,必须写0,len
                sb.append(new String(bytes,0,len));
            }
            System.out.println("打印内容:"+sb);
            // 关闭输入流
            in.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

字符流

Writer 写入字符流的抽象类,子类必须实现现有的方法仅有wirte(char[],int,int),flush()和close()。但是,多数子类将重写此处定义的一
些方法,以提供更高的效率和其他功能。与OutputStream一样,对文件操作使用,FileWriter类完成。

Reader 用于读取字符流的抽象类,子类必须实现现有方法read(char[],int,int)和cloase()。但是,多数子类将重写此处定义的方法,以提供更高
的效率。使用FileRead类进行实例化操作。

字节流与字符流区别:

在所有的流操作里,字节永远都是最基础的。任何基于字节的操作都是正确的。无论你的文本文件还是二进制文件。
如果确认流里面只有打印字符的字符,包括英文的的文字,也包括中文,那么可以考虑用字符流。由于编码不同,多字节的字符可能占用多个字节,比如
GBK的汉字占用两个字节,而UTF-8的汉字占用3个字节,所以,字符流是根据指定编码,讲1个或多个字节转换为java里面unicode的字符,然后进行
操作。字符操作一般使用Writer,Reader等,字节操作一般都是InputStream,OutputStream以及各种包装类,比如BufferedInputStream和
BufferedOutputStream等。

不管什么用字节流肯定没问题

/**
 * 字符流:解决多字节的文本文件形式
 * 字符输出流:Writer,对文件的操作使用子类:FileWriter
 * 字符输入流:Reader,对文件的操作使用子类:FileReader
 * 每次操作的单位是一个字符
 * 文件字符操作流程,自带缓存,默认大小1024字节,在缓存满后,或手动刷新会把缓存清空,或关闭流时,会把数据写入文件
 */
public class CharStreamDemo {
    public static void main(String[] args) {
        out();
        in();
    }

    private static void out() {
        // 1. 确定目标文件
        File file = new File("/Users/liuyan/IdeaProjects/BiliFengJia/src/a.txt");
        try {
            Writer out = new FileWriter(file);
            String str = "hell,hello";
            out.write(str);
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void in() {
        // 1. 确定目标文件
        File file = new File("/Users/liuyan/IdeaProjects/BiliFengJia/src/a.txt");
        try {
            Reader in = new FileReader(file);
            int len = -1;
            char[] ch = new char[1];
            StringBuilder sb = new StringBuilder();
            while ((len = in.read(ch)) != -1) {
                sb.append(new String(ch,0,len));
            }
            System.out.println(sb);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

文件拷贝

/**
 * 文件的拷贝
 * 从一个输入流中读取数据,然后同时通过输出流写入目标位置
 * 一边读,一边写
 */
public class CopyFileDemo {
    public static void main(String[] args) {
        // 1.原文件,2.目标文件
        copy("/Users/liuyan/IdeaProjects/BiliFengJia/src/a.txt", "/Users/liuyan/IdeaProjects/BiliFengJia/src/b.txt");
    }

    /**
     * src 原文件
     * target 目标文件
     */
    private static void copy(String src, String target) {
        File srcFile = new File(src);
        File targetFile = new File(target);
        InputStream in = null;
        OutputStream out = null;
        try {
            in = new FileInputStream(srcFile);
            out = new FileOutputStream(targetFile);
            byte[] bytes = new byte[1024];
            int len = -1;
            while ((len = in.read(bytes)) != -1) {
                out.write(bytes, 0, len);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) in.close();
                if (out != null) out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

字节字符转换流

转换流:可以将一个字节流转换为字符流,也可以将一个字符流转换为字节流。
OutputStreamWriter:可以将输出的字符流转换为字节流的输出形式
InputStreamReader:将输入的字节流转换为字符流输入形式

/**
 * 转换流
 * 跟文本相关的时候才会用到转换流,都是用来处理字符的
 */
public class ChangeStreamDemo {
    public static void main(String[] args) {
        try {
            InputStream is = new FileInputStream("/Users/liuyan/IdeaProjects/BiliFengJia/src/a.txt");
            read(is);

            OutputStream out = new FileOutputStream("/Users/liuyan/IdeaProjects/BiliFengJia/src/a.txt");
            write(out);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

    }

    private static void write(OutputStream out){
        try {
            Writer writer = new OutputStreamWriter(out);
            writer.write("hello 青岛");
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*别人给你个输入流,可能是文件,可能是网络上的文件*/
    private static void read(InputStream in) {
        try {
            Reader reader = new InputStreamReader(in, "utf-8");
            char[] cs = new char[1024];
            int len = -1;
            while ((len = reader.read(cs)) != -1) {
                System.out.println(new String(cs, 0, len));
            }
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

缓冲流

对文件或其它目标频繁的读写操作,效率低,性能差。
使用缓冲流的好处是,能够更高效的读写信息,原理是讲数据先缓冲起来,然后一起写入或读取出来。
BufferedInputStream:为另一个输入流添加一些功能,在创建BufferedInputStream时,会创建一个内部缓冲区数组,用于缓冲数据。
BufferedOutputStream:通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。
BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符流、数组和行的高效读取。
BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

/**
 * 缓存的目的:
 * 解决在写入文件操作时,频繁的操作文件所带来的性能降低的问题
 * 默认缓存大小 8192 ,8kb,每次写入时,先存储到缓存中的byte数组里,当数组存满时,会把数组
 * 中的数据写入文件,并且缓存下标归零
 */
public class BufferStreamDemo {
    public static void main(String[] args) {
        byteWriter();
        byteReader();
    }

    private static void byteWriter() {

        File file = new File("/Users/liuyan/IdeaProjects/BiliFengJia/src/a.txt");
        try {
            OutputStream out = new FileOutputStream(file);
            // 构造一个字节缓冲流
            BufferedOutputStream bos = new BufferedOutputStream(out);
            String info = "缓冲aa";
            bos.write(info.getBytes());
            bos.close();
//            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void byteReader() {
        File file = new File("/Users/liuyan/IdeaProjects/BiliFengJia/src/a.txt");
        try {
            InputStream in = new FileInputStream(file);
            BufferedInputStream bis = new BufferedInputStream(in);
            int len = -1;
            byte[] bytes = new byte[1024];
            while ((len = bis.read(bytes)) != -1) {
                System.out.println(new String(bytes,0,len));
            }
            bis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

字节数组流

ByteArrayInputStream:包含一个内部缓冲区,改缓冲区包含从流中读取的字节。内部计数器跟踪read方法要提供的下一个字节。关闭ByteArrayInputStream无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何IOException。
ByteArrayOutputStream:输出流,其中数据被写入一个byte数组。缓冲区会随着数据的不断写入而自增长。可使用toByteArray()和toString()获取数据。关闭ByteArrayOutputStream无效。此类中的方法在关闭此流后仍可被调用,而不产生任何IOException。

/**
 * 字节数组流跟文件没有关系
 * 字节数组流,基于内存操作,内部维护着一个字节数组,我们可以利用流的读取机制来处理字符串
 * 无需关闭,因为不会报IO异常
 */
public class ByteArrayStreamDemo {
    public static void main(String[] args) {
        bytreArray();
    }

    private static void bytreArray() {
//        File file = new File("/Users/liuyan/IdeaProjects/BiliFengJia/src/a.txt");
        // 把字符串中的字母提出来,包含大小写
        String s = "123456abcdEFAGAC%^&*(";
        ByteArrayInputStream bis = new ByteArrayInputStream(s.getBytes());
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        int curr = -1;
        while ((curr = bis.read()) != -1) {
            // 97 -122 大写 65-90
            if ((curr >= 65 && curr <= 90) || (curr >= 97 && curr <= 122)) {
                bos.write(curr);
            }
        }
        // 无需关闭,字节数组流是基于内存的操作流
        System.out.println(bos.toString());
        int lenth = bos.toByteArray().length;
        System.out.println(lenth);
    }
}

文件分割

我们把一个视频文件按照指定大小分割成多个视频文件

public class FileSplitDemo {
    public static void main(String[] args) {
        File file = new File("/Users/liuyan/Documents/视频/xx视频/ac.mp4");
        fileSplitCut(file, 1024 * 1024);
        merage();
    }


    /**
     * 文件的分割
     * targetFile 要分割的目标文件
     * cutsize 每个文件的大小
     */
    private static void fileSplitCut(File targetFile, long cutsize) {
        if (targetFile == null) return;
        // 计算总分割的文件数
        int num = targetFile.length() % cutsize == 0 ? (int) (targetFile.length() / cutsize)
                : (int) (targetFile.length() / cutsize + 1);
        // 我总文件大小是15M多,按照1M分割,这里输出15
        System.out.println(num);
        try {
            // 构造一个文件输入流,总的,一直在读的,读到文件结尾
            BufferedInputStream in = new BufferedInputStream(new FileInputStream(targetFile));
            BufferedOutputStream out = null; // 读到指定文件大小的时候在生成一个文件
            byte[] bytes = null;// 每次要读取的字节数
            int len = -1;// 每次读取实际的长度
            int count = 0;// 每一个文件要读取的次数 20M 每次读1024,4万多次,1024可以调大一些
            // 循环次数为生成文件的个数
            for (int i = 0; i < num; i++) {
                out = new BufferedOutputStream(new FileOutputStream(new File("/Users/liuyan/IdeaProjects/BiliFengJia/src/" + (i + 1) + "-temp-" + targetFile.getName())));
                // 判断每个文件的大小是小于1024还是等于1024
                if (cutsize <= 1024) {
                    bytes = new byte[(int) cutsize];
                    // 就读一次
                    count = 1;
                } else {
                    bytes = new byte[1024];
                    // 这个count 不包括最后一次,有可能cutsize除1024会有余数
                    count = (int) cutsize / 1024;
                }
                // 如果整除,就直接搞定
                while (count > 0 && (len = in.read(bytes)) != -1) {
                    out.write(bytes, 0, len);
                    out.flush();
                    count--;
                }
                // 如果不整除还需要再来一次,比如我15.6M的文件我按照1M来分割15次最后的6 还需要在来一次
                // 计算余数,每个文件大小除1024的余数,决定是否要再读取一次
                if (cutsize % 1024 != 0) {
                    bytes = new byte[(int) cutsize % 1024];
                    len = in.read(bytes);
                    out.write(bytes, 0, len);
                    out.flush();
                    out.close();
                }
            }
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

分割后的,按照1M 分割的


image.png

相关文章

  • File与IO

    File File类:表示文件和目录路径名的抽象。File类可以实现文件的创建、删除、重命名、得到路径、创建时间等...

  • File与IO基础

    IO流的作用:持久化到磁盘 File类的使用 File类基本概念 文件和文件夹都是用File类来表示。 File类...

  • Java篇-IO处理

    一 : 文件 凡是与输入输出相关的类,接口等定义在java.io包下File类->java.io.File.Fil...

  • 2019-09-28

    Java的IO处理 IO类与File类的区别 IO类关注文件内的内容。File类关注文件在磁盘上的存储。因此处理文...

  • Chapter 9 . Java IO

    阅读原文 Chapter 9 . Java IO 9.1 IO---File 类 java.io.File类:文件...

  • Java—File类详解及实践

    File类介绍 File类概述   File类是java.io包下代表与平台无关的文件和目录。File可以新建、删...

  • JAVA 中的 IO 流

    File 类的使用 java.io.File 类:文件和文件目录路径的抽象表示形式,与平台无关 File 能新建、...

  • 2018-04-26

    package com.test; import java.io.File;import java.io.File...

  • Java IO流笔记

    File类 功能与作用 java.io.File类:文件和文件目录路径的抽象表示形式,与平台无关 File能新建、...

  • 中级05 - File与IO

    IO就是输入输出。IO 的本质就是字节流。 一切文件的本质就是一段字节流,不管是文本文件(txt/代码/HTML等...

网友评论

      本文标题:File与IO

      本文链接:https://www.haomeiwen.com/subject/mfuuzctx.html