File类与IO流

本文详细介绍了Java中的File类,包括其用于表示文件和目录、获取文件属性、路径信息以及进行文件操作的方法。此外,还讨论了IO流的基本概念,如输入输出流、字节流和字符流,并举例展示了FileInputStream、FileOutputStream、FileReader和FileWriter的使用。文章还涉及了缓冲流、转换流和文件复制的实现。最后,提到了文件过滤和目录操作的相关API。
摘要由CSDN通过智能技术生成

一、java.io.File类
1、File类:文件和目录路径名的抽象表示形式。
(1)无论是表示文件还是目录(文件夹)都是用File类的对象
(2)无论是表示文件还是目录,都是通过指定“路径名”来表示

例如:表示D盘的D:\to_student\尚硅谷_210728Java_柴林燕_JavaSE\ppt\尚硅谷_柴林燕_JDK8的安装及配置.pdf文件
     表示D盘的D:\to_student\尚硅谷_210728Java_柴林燕_JavaSE\ppt文件夹

2、File类的API
(1)获取文件或目录的一些基本信息:文件名、大小、时间等属性

其中有一个方法需要说明:
long length():它只能获取到文件的大小,不能直接获取文件夹的大小。如果文件不存在,返回0L。

    思考?如何获取文件夹的大小?

(2)获取文件或目录的一些路径信息
相对路径:除了绝对路径以外都是相对路径
绝对路径:从根目录开始指定的路径是绝对路径
        windows操作系统是从盘符开始  D:\to_student\尚硅谷_210728Java_柴林燕_JavaSE\ppt\尚硅谷_柴林燕_JDK8的安装及配置.pdf
        linux操作系统是从 / 开始

getPath()构造路径:new File对象时,构造器传的路径
getAbsolutePath() :
        如果构造路径就是绝对路径,就和构造路径一样
        如果构造路径就是相对路径,就用    当前项目或当前模块的路径 + 构造路径
getCanonicalPath():如果路径中有..等非规范的路径表示方式,就对它进行解析

(3)判断某个File对象是代表文件还是代表目录?
isFile():是否是文件      文件存在并且是个文件才会返回true
isDirectory():是否是目录   目录存在并且是个目录才会返回true

public class TestFile {
    @Test
    public void test09(){
        File dir = new File("D:/1.txt");  //不存在
        System.out.println("是否是文件:" + dir.isFile());//false
        System.out.println("是否是目录:" + dir.isDirectory());//false
    }

    @Test
    public void test08(){
        File dir = new File("D:\\to_student\\尚硅谷_210728Java_柴林燕_JavaSE\\ppt");
        System.out.println("是否是文件:" + dir.isFile());//false
        System.out.println("是否是目录:" + dir.isDirectory());//true
    }

    @Test
    public void test07() throws IOException {
        File file = new File("D:\\to_student\\尚硅谷_210728Java_柴林燕_JavaSE\\ppt\\尚硅谷_柴林燕_JDK8的安装及配置.pdf");
        System.out.println("是否是文件:" + file.isFile());//true
        System.out.println("是否是目录:" + file.isDirectory());//false
    }

    public static void main(String[] args) throws IOException{
        //main相对于当前IDEA的project的根目录
        File file = new File("..\\..\\尚硅谷_柴林燕_JDK8的安装及配置.pdf");//相对路径  new对象不会自动创建对应的文件,只是在JVM的堆中创建了一个对象
        System.out.println("构造路径(普通路径):" + file.getPath());
        System.out.println("绝对路径:" + file.getAbsolutePath()); //(构造路径是相对路径的话)绝对路径 = 当前项目或当前模块的路径 + 构造路径
        System.out.println("规范路径:" + file.getCanonicalPath());
        System.out.println("是否存在:" + file.exists());//false
        /*
        构造路径(普通路径):..\..\尚硅谷_柴林燕_JDK8的安装及配置.pdf
        绝对路径:D:\atguigu\javaee\JavaSE20210728\code\..\..\尚硅谷_柴林燕_JDK8的安装及配置.pdf
        规范路径:D:\atguigu\javaee\尚硅谷_柴林燕_JDK8的安装及配置.pdf
        是否存在:false
         */
    }
    @Test
    public void test06() throws IOException {
        //JUnit相对于当前IDEA的模块的根目录
        File file = new File("..\\..\\尚硅谷_柴林燕_JDK8的安装及配置.pdf");//相对路径  new对象不会自动创建对应的文件,只是在JVM的堆中创建了一个对象
        System.out.println("构造路径(普通路径):" + file.getPath());
        System.out.println("绝对路径:" + file.getAbsolutePath());//(构造路径是相对路径的话) 绝对路径 = 当前项目或当前模块的路径 + 构造路径
        System.out.println("规范路径:" + file.getCanonicalPath());
        System.out.println("是否存在:" + file.exists());//false
        System.out.println("文件大小:" + file.length());
        /*
        构造路径(普通路径):..\..\尚硅谷_柴林燕_JDK8的安装及配置.pdf
        绝对路径:D:\atguigu\javaee\JavaSE20210728\code\day0828_teacher_code\..\..\尚硅谷_柴林燕_JDK8的安装及配置.pdf
        规范路径:D:\atguigu\javaee\JavaSE20210728\尚硅谷_柴林燕_JDK8的安装及配置.pdf
         */
    }

    @Test
    public void test05() throws IOException {
        File file = new File("D:\\to_student\\尚硅谷_210728Java_柴林燕_JavaSE\\ppt\\尚硅谷_柴林燕_JDK8的安装及配置.pdf");
        System.out.println("构造路径(普通路径):" + file.getPath());
        System.out.println("绝对路径:" + file.getAbsolutePath());
        System.out.println("规范路径:" + file.getCanonicalPath());
        /*
        路径:D:\to_student\尚硅谷_210728Java_柴林燕_JavaSE\ppt\尚硅谷_柴林燕_JDK8的安装及配置.pdf
        绝对路径:D:\to_student\尚硅谷_210728Java_柴林燕_JavaSE\ppt\尚硅谷_柴林燕_JDK8的安装及配置.pdf
        规范路径:D:\to_student\尚硅谷_210728Java_柴林燕_JavaSE\ppt\尚硅谷_柴林燕_JDK8的安装及配置.pdf
         */
    }


    @Test
    public void test04(){
        File dir = new File("D:\\to_student\\尚硅谷_210728Java_柴林燕_JavaSE\\ppt");
        System.out.println("文件夹的大小:" + dir.length());//8192  不正确
    }

    @Test
    public void test03(){
        //演示获取文件的一些基本信息
        File file = new File("D:\\to_student\\尚硅谷_210728Java_柴林燕_JavaSE\\ppt\\尚硅谷_柴林燕_JDK8的安装及配置.pdf");
        System.out.println("文件名:" + file.getName());
        System.out.println("文件大小:" + file.length() +"字节");//数组.length属性,字符串.length()方法,文件对象.length()方法
        System.out.println("最后修改时间:" + file.lastModified() +"毫秒"); //距离1970年1月1日 0:0:0 0毫秒的一个时间差

        long time = file.lastModified();
        Date date = new Date(time);
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        System.out.println("最后修改时间:" + sf.format(date));

        System.out.println("文件是否可读:" + file.canRead());
        System.out.println("文件是否可写:" + file.canWrite());
        System.out.println("文件是否存在:" + file.exists());
        //...
    }


    @Test
    public void test02(){
        //表示D盘的D:\to_student\尚硅谷_210728Java_柴林燕_JavaSE\ppt文件夹
        File dir = new File("D:\\to_student\\尚硅谷_210728Java_柴林燕_JavaSE\\ppt");//dir这个对象是代表ppt这个文件夹
    }

    @Test
    public void test01(){
        //表示D盘的D:\to_student\尚硅谷_210728Java_柴林燕_JavaSE\ppt\尚硅谷_柴林燕_JDK8的安装及配置.pdf文件
        File file1 = new File("D:\\to_student\\尚硅谷_210728Java_柴林燕_JavaSE\\ppt\\尚硅谷_柴林燕_JDK8的安装及配置.pdf");
        //上面的\\是windows平台支持的方式

        File file2 = new File("D:/to_student/尚硅谷_210728Java_柴林燕_JavaSE/ppt/尚硅谷_柴林燕_JDK8的安装及配置.pdf");
        //下面这个/是所有平台都支持的方式
    }
}

3、File类的API:关于文件或目录的操作
(1)boolean createNewFile()  :创建一个新文件
(2)boolean mkdir():创建最末尾的一级目录
   boolean mkdirs() :创建多级目录
(3)boolean delete() :删除
    delete()可以删除文件
    delete()可以删除空目录

    思考?如何删除非空目录?
(4)boolean renameTo(File dest):重命名文件或目录

public class TestFileOperate {
    @Test
    public void test7() throws IOException {
        File dir = new File("d:/java");
        File dest = new File("d:/javase");
        dir.renameTo(dest);
    }

    @Test
    public void test6() throws IOException {
        File dir = new File("d:/java");
        dir.delete();
    }

    @Test
    public void test5() throws IOException {
        File dir = new File("d:/temp");
        dir.delete();
    }


    @Test
    public void test4() throws IOException {
        File file = new File("d:/1.txt");
        file.delete();
    }

    @Test
    public void test3() throws IOException {
        File dir = new File("d:/java/io/chai");
//        dir.mkdir();
        dir.mkdirs();
    }

    @Test
    public void test2() throws IOException {
        File dir = new File("d:/temp");
        dir.mkdir();
    }
    @Test
    public void test() throws IOException {
        File file = new File("d:/1.txt");
        file.createNewFile();
    }
}

4、File的API:关于文件夹的下一级的获取
(1)String[] list():返回值类型是String[]
(2)File[] listFiles() :返回值类型是File[]

    思考:如何获取下一级,如果下一级还是目录,继续获取它的下一级。
    思考:统计文件夹大小
    思考:删除非空目录

public class TestListDir {
    //思考:删除非空目录
    @Test
    public void test04(){
        File dir = new File("D:\\to_student - 副本");
        forceDir(dir);
    }

    public void forceDir(File dir){
        if(dir.isDirectory()){//如果是目录,先删除目录的下一级
            //(1)先获取它的下一级
            File[] files = dir.listFiles();
            //(2)遍历挨个删除下一级
            for (File sub : files) {//sub是dir的下一级
                forceDir(sub);
            }
        }
        //经过上面的if,如果dir是文件,上面的if条件不成立,直接删除文件
        //经过上面的if,如果dir是目录,上面的if可以把dir的下一级删除,然后删除dir这个空目录
        dir.delete();
    }

    //思考:统计文件夹大小
    @Test
    public void test03(){
        File dir = new File("D:\\to_student");
        System.out.println(size(dir) +"字节");//5847224217字节
    }
    public long size(File dir){
        if(dir.isFile()){
            return dir.length();
        }else if(dir.isDirectory()){
            long sum = 0;
            //累加dir的所有下级的大小
            //(1)获取dir的下一级
            File[] files = dir.listFiles();
            //(2)遍历并累加每一个下一级的大小
            for (File sub : files) {//sub是dir的下一级
//                sum += sub.length();//因为sub可能是一个文件,也可能是文件夹,如果文件夹的话,这样是错误
                sum += size(sub);
            }
            return sum;
        }else{
            return 0L;
        }
    }


    @Test
    public void test02(){
        File dir = new File("D:\\to_student");
        listAllSub(dir);
    }

    //思考:如何获取下一级,如果下一级还是目录,继续获取它的下一级。
    public void listAllSub(File dir){
        if(dir.isDirectory()) {
            File[] files = dir.listFiles();
            for (File sub : files) {//sub是dir的下一级, sub可能是一个文件,也可能是一个文件夹
                listAllSub(sub);//递归调用
            }
        }
        System.out.println(dir);
    }
    
    @Test
    public void test01(){
        File dir = new File("D:\\to_student");
        String[] strings = dir.list();
        for (int i = 0; i < strings.length; i++) {
            System.out.println(strings[i]);
        }
    }
}

5、File类中关于文件或目录的过滤问题:
    File[] listFiles(FileFilter filter)

FileFilter接口:
    boolean accept(File pathname)  抽象方法,重写时,告诉File类的listFiles方法,什么样文件或目录需要留下来

public class TestFileFilter {
    @Test
    public void test02(){
        File dir = new File("D:\\to_student\\尚硅谷_210728Java_柴林燕_JavaSE\\预装软件");
        ArrayList<File> allExeSubFiles = getAllExeSubFiles(dir);
        for (File allExeSubFile : allExeSubFiles) {
            System.out.println(allExeSubFile);
        }
    }

    public ArrayList<File> getAllExeSubFiles(File dir){
        ArrayList<File> list = new ArrayList<File>();
        if(dir.isFile()){
            String name = dir.getName();
            if(name.endsWith(".exe")){
                list.add(dir);
            }
        }else if(dir.isDirectory()){
            //需求:列出它的下一级,只想看.exe的文件
            File[] exeSubFiles = dir.listFiles(new FileFilter() {
                @Override
                public boolean accept(File pathname) { //这个方法是在File类的listFiles方法体中调用
                    //File pathname是在listFiles方法体中获取的dir的下一级(可能是一个文件,可能是一个目录)
                    //pathname.getName()获取下一级的文件或目录的名字
                    //文件或目录名  以 ".exe"结尾
                    return pathname.getName().endsWith(".exe") || pathname.isDirectory();
                }
            });

            for (File exeSubFile : exeSubFiles) {//exeSubFile可能是一个.exe文件,或者是文件夹
                ArrayList<File> allExeSubFiles = getAllExeSubFiles(exeSubFile);
                list.addAll(allExeSubFiles);
            }
        }
        return list;
    }


    @Test
    public void test01(){
        File dir = new File("D:\\to_student\\尚硅谷_210728Java_柴林燕_JavaSE\\预装软件");

        //需求:列出它的下一级,只想看.exe的文件
        File[] exeSubFiles = dir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) { //这个方法是在File类的listFiles方法体中调用
                //File pathname是在listFiles方法体中获取的dir的下一级(可能是一个文件,可能是一个目录)
                //pathname.getName()获取下一级的文件或目录的名字
                //文件或目录名  以 ".exe"结尾
                return pathname.getName().endsWith(".exe");
            }
        });

        for (File exeSubFile : exeSubFiles) {
            System.out.println(exeSubFile);
        }
    }
}

二、IO
1、IO两个字母代表的意思:
I: input输入
O:output输出

数据的读和写。

2、IO的分类
(1)根据方向分:
A:输入流
B:输出流

(2)根据操作数据单位分:
A:字节流:以字节为最小单位
B:字符流:以字符为最小单位

(3)根据IO流的角色划分
A:节点流:和数据节点相连接,数据节点有:文件、网络、内存等
B:处理流:在节点流的基础上增加辅助功能的,或者增加装饰功能的,又称为包装流、装饰流
        辅助功能:缓存、编码和解码、序列化和反序列化等

3、IO流有四个基本父类,抽象基类:
InputStream:字节输入流系列的超级父类
OutputStream:字节输出流系列的超级父类
Reader:字符输入流系列的超级父类
Writer:字符输出流系列的超级父类

4、其他类型
(1)文件IO流
FileInputStream:文件字节输入流
FileOutputStream:文件字节输出流
FileReader:文件字符输入流
FileWriter:文件字符输出流

FileInputStream和FileOutputStream适用于读和写任意类型的文件,包括文本文件,视频,音频,图片等。
FileReader和FileWriter只能用于读和写纯文本文件,而且文件内容的编码(字符集)与当前平台要一致。

(2)缓冲IO流
BufferedInputStream:缓冲字节输入流或字节缓冲输入流,它只能直接给InputStream系列的IO流增加缓冲功能
BufferedOutputStream:字节缓冲输出流,它只能直接给OutputStream系列的IO流增加缓冲功能
BufferedReader:字符缓冲输入流,它只能直接给Reader系列的IO流增加缓冲功能
BufferedWriter:字符缓冲输出流,它只能直接给Writer系列的IO流增加缓冲功能

(3)转换流
InputStreamReader:把字节流转换为字符流,把字节流中的数据转换为字符流中的数据,
        把字节-->字符:“解码”
OutputStreamWriter:从IO流感觉也是把字节流转为字符流,但是从数据来看,把字符流的数据转为字节流中的数据
        把字符-->字节:“编码”

(4)数据流
DataInputStream:用于Java的各种基本数据类型的数据和字符串的读取
DataOutputStream:用于输出Java的各种基本数据类型的数据和字符串

(5)对象流
ObjectInputStream:用于Java对象的读取
ObjectOutputStream:用于输出Java对象

(6)打印流
PrintStream:字节打印流
    代表:System.out
PrintWriter:字符打印流
    代表:web阶段从服务器端给客户端反馈消息时用的打印流
        request(请求):客户端给服务器端发“请求”
        response(相应):服务器端给客户端发送“响应”

<1>=====================================================================

FileInputStream:用于读文件,以“字节”方式读取文件内容
使用FileInputStream的步骤:
第一步:要告诉FileInputStream从哪个文件读取内容
  创建FileInputStream的对象,通过构造器的参数指定要读取的文件
   FileInputStream fis = new FileInputStream("d:/1.txt");

第二步:选择读取的方法,这些方法适用于所有的InputStream系列的IO流
int read():读取一个字节的内容,返回的是一个字节的内容的int值
            如果流中没有数据了,返回-1
int read(byte[] data):一次读取多个字节,返回的是读取的字节总数。
            如果流中没有数据了,返回-1。最多一次读取data.length个字节,
            读取的数据依次放到data的元素中,从[0]元素开始放
int read(byte[] data, int off, int len) : 一次读取多个字节,返回的是读取的字节总数。
            如果流中没有数据了,返回-1。最多一次读取len个字节,
            读取的数据依次放到data的元素中,从[off]元素开始放

第三步:关闭IO流
调用IO流对象的close()

关闭IO流的目的:释放对应的内存等资源,包括JVM中和JVM以外的OS系统中的内存

public class TestFileInputStream {
    @Test
    public void test06() throws IOException {
        //需求:读取d:/2.txt文件
        FileInputStream fis = new FileInputStream("d:/2.txt");//文件内容比较多,有很多字符

        byte[] data = new byte[10];
        int len;
        /*
        第一个事情,从fis流中读取了多个字节,放到data数组中
        第二个事情,把本次读取的字节数赋值给len变量
        第三个事情:判断len是否是-1,如果是-1说明fis中已经没有数据了
                                         */
        while((len=fis.read(data)) != -1){ //while的条件中做了3个事情
//            System.out.println(Arrays.toString(data));
            System.out.println(new String(data,0, len));
        }

        fis.close();
    }

    @Test
    public void test05() throws IOException {
        //需求:读取d:/2.txt文件
        FileInputStream fis = new FileInputStream("d:/2.txt");//文件内容比较多,有很多字符

        //当文件内容超过10个字节时,那么一次最多只能读取10个字节
        byte[] data = new byte[10];
        int len = 0;

        //第一次读取
        len = fis.read(data);
        System.out.println("len = " + len);
        System.out.println(Arrays.toString(data));

        System.out.println("-------------------");
        //第二次读取
        len = fis.read(data);//这一次读取的2个字节,放到了data数组的[0][1]元素中,剩下的元素是上次读取的内容
        System.out.println("len = " + len);//2
        System.out.println(Arrays.toString(data));

        System.out.println("-------------------");
        //第三次读取
        len = fis.read(data);
        System.out.println("len = " + len);//-1  流中没有数据了
        System.out.println(Arrays.toString(data));//本次data中的元素都是之前读取的

        fis.close();
    }

    @Test
    public void test04() throws IOException {
        //需求:读取d:/1.txt文件
        FileInputStream fis = new FileInputStream("d:/1.txt");//文件内容是abcd

        System.out.println(fis.read());//97 调用一次read()方法读取一个字节
        System.out.println(fis.read());//98
        System.out.println(fis.read());//99
        System.out.println(fis.read());//100
        System.out.println(fis.read());//-1

        fis.close();
    }


    @Test
    public void test03() throws IOException {
        //需求:读取d:/2.txt文件
        FileInputStream fis = new FileInputStream("d:/2.txt");//文件内容比较多,有很多字符

        //当文件内容超过10个字节时,那么一次最多只能读取10个字节
        byte[] data = new byte[10];
        int len = fis.read(data);
        System.out.println("len = " + len);
        System.out.println(Arrays.toString(data));

        fis.close();
    }

    @Test
    public void test02() throws IOException {
        //需求:读取d:/1.txt文件
        FileInputStream fis = new FileInputStream("d:/1.txt");//文件内容是abcd

        byte[] data = new byte[10];
        int len = fis.read(data);
        System.out.println("len = " + len);
        System.out.println(Arrays.toString(data));

        fis.close();
    }
    
    @Test
    public void test01() throws IOException {
        //需求:读取d:/1.txt文件
        FileInputStream fis = new FileInputStream("d:/1.txt");//文件内容是abcd

        int data = fis.read();
        System.out.println(data);//97

        fis.close();
    }
}

FileOutputStream:用于输出数据到文件,以“字节“方式
步骤:
第一步:告诉FileOutputStream把数据输出到哪个文件
    创建FileOutputStream的对象时,通过构造器的参数告诉文件路径名
    FileOutputStream fos = new FileOutputStream("d:/1.txt");

第二步:调用输出内容的方法
void  write(int c):一次输出一个字节
void write(byte[] cbuf):输出整个字节数组
void write(byte[] cbuf, int off, int len):输出字节输出的一部分

 第三步:关闭

注意:
(1)默认情况下,FileOutputStream以覆盖的方式输出内容到文件,即原来文件的内容会被覆盖掉。
 可以使用“追加”模式输出内容到文件。
(2)FileWriter和FileOutputStream输出内容到文件,如果文件不存在,会自动创建这个文件
   FileInputStream和FileReader如果要读取的文件不存在,报错FileNotFoundException

public class TestFileOutputStream {
    @Test
    public void test01() throws IOException {
        FileOutputStream fos = new FileOutputStream("d:/1.txt",true);
        fos.write("helle".getBytes());//字符串变为字节数组的方法 getBytes()
        fos.close();
    }
}

<2>======================================================================

FileReader:用于读文件,以“字符”方式读取文件内容
使用FileReader的步骤:
第一步:要告诉FileReader从哪个文件读取内容
  创建FileReader的对象,通过构造器的参数指定要读取的文件
   FileReader fr = new FileReader("d:/1.txt");

第二步:选择读取的方法,这些方法适用于所有的Reader系列的IO流
int read():读取一个字符的内容,返回的是一个字符的内容的int值
            如果流中没有数据了,返回-1
int read(char[] data):一次读取多个字符,返回的是读取的字符总数。
            如果流中没有数据了,返回-1。最多一次读取data.length个字符,
            读取的数据依次放到data的元素中,从[0]元素开始放
int read(char[] data, int off, int len) : 一次读取多个字符,返回的是读取的字符总数。
            如果流中没有数据了,返回-1。最多一次读取len个字符,
            读取的数据依次放到data的元素中,从[off]元素开始放

第三步:关闭IO流
调用IO流对象的close()

关闭IO流的目的:释放对应的内存等资源,包括JVM中和JVM以外的OS系统中的内存

public class TestFileReader {
    @Test
    public void test06() throws IOException {
        //需求:读取d:/2.txt文件
        FileReader fr = new FileReader("d:/2.txt");//文件内容比较多,有很多字符

        char[] data = new char[10];
        int len;
        /*
        第一个事情,从fr流中读取了多个字节,放到data数组中
        第二个事情,把本次读取的字符数赋值给len变量
        第三个事情:判断len是否是-1,如果是-1说明fis中已经没有数据了
                                         */
        while((len=fr.read(data)) != -1){ //while的条件中做了3个事情
//            System.out.println(Arrays.toString(data));
            System.out.println(new String(data,0, len));
        }

        fr.close();
    }
}

FileWriter:用于输出数据到文件,以“字符”方式
步骤:
第一步:告诉FileWriter把数据输出到哪个文件
    创建FileWriter的对象时,通过构造器的参数告诉文件路径名
    FileWriter fw = new FileWriter("d:/1.txt");

第二步:调用输出内容的方法
void  write(int c):一次输出一个字符
void write(char[] cbuf):输出整个字符数组
void write(char[] cbuf, int off, int len):输出字符输出的一部分
 void write(String str) :输出字符串
 void write(String str, int off, int len)  :输出字符串的一部分

 第三步:关闭

注意:
(1)默认情况下,FileWriter以覆盖的方式输出内容到文件,即原来文件的内容会被覆盖掉。
 可以使用“追加”模式输出内容到文件。
(2)FileWriter和FileOutputStream输出内容到文件,如果文件不存在,会自动创建这个文件
   FileInputStream和FileReader如果要读取的文件不存在,报错FileNotFoundException

public class TestFileWriter {
    @Test
    public void test04() throws IOException {
        FileWriter fw = new FileWriter("d:/3.txt");

        fw.write("hello");

        fw.close();
    }


    @Test
    public void test03() throws IOException {
        FileWriter fw = new FileWriter("d:/1.txt",true);//true代表追加

        fw.write("java");

        fw.close();
    }

    @Test
    public void test02() throws IOException {
        FileWriter fw = new FileWriter("d:/1.txt");

        fw.write("hello");

        fw.close();
    }

    @Test
    public void test01() throws IOException {
        FileWriter fw = new FileWriter("d:/1.txt");

        fw.write('a');
        fw.write('尚');
        fw.write(99);//字符的编码

        fw.close();

    }
}

复制

public class FileTools {
    public static void main(String[] args) throws IOException {
        copy("D:\\atguigu\\javaee\\JavaSE20210728\\video\\day0827_21video\\day0827_01多线程的相关概念.avi","d:/1.avi");
    }
    /**
     * 把srcFile的文件复制一份,存在destFile文件中,要求适用于复制任何类型的文件
     * @param srcFile
     * @param destFile
     */
    public static void copy(String srcFile, String destFile) throws IOException {
        //文件的复制过程:从一个文件“读”数据,“写”到另一个文件中
        //从srcFile文件读取,写到destFile文件
        //(1)先创建两个IO流,因为要求适用于复制任何类型的文件,所以选择FileInputStream和FileOutputStream
        FileInputStream fis = new FileInputStream(srcFile);
        FileOutputStream fos = new FileOutputStream(destFile);

        //(2)一边从fis流中读,一边写到fos中
        byte[] data = new byte[1024];
        int len;
        while((len = fis.read(data)) != -1){
//            fos.write(data);//复制后可能会多出数据来
            fos.write(data,0,len);//本次读几个,写几个字节,本次读了len个字节
        }

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

    /**
     * 把srcFile的文件复制一份,存在destFile文件中,要求适用于复制任何类型的文件
     * @param srcFile
     * @param destFile
     */
    public static void copyBuffer(String srcFile, String destFile) throws IOException {
        //文件的复制过程:从一个文件“读”数据,“写”到另一个文件中
        //从srcFile文件读取,写到destFile文件
        //(1)先创建两个IO流,因为要求适用于复制任何类型的文件,所以选择FileInputStream和FileOutputStream
        FileInputStream fis = new FileInputStream(srcFile);
        FileOutputStream fos = new FileOutputStream(destFile);

        //增加缓冲流
        BufferedInputStream bis = new BufferedInputStream(fis);
        BufferedOutputStream bos = new BufferedOutputStream(fos);

        //(2)一边从bis流中读,一边写到bos中
        byte[] data = new byte[1024];
        int len;
        while((len = bis.read(data)) != -1){
            bos.write(data,0,len);//本次读几个,写几个字节,本次读了len个字节
        }

        //(3)关闭
        bis.close();
        bos.close();
        fos.close();
        fis.close();
    }
}

<3>======================================================================

缓冲流:Buffered开头的四个IO流
BufferedInputStream:缓冲字节输入流或字节缓冲输入流,它只能直接给InputStream系列的IO流增加缓冲功能
BufferedOutputStream:字节缓冲输出流,它只能直接给OutputStream系列的IO流增加缓冲功能
BufferedReader:字符缓冲输入流,它只能直接给Reader系列的IO流增加缓冲功能
BufferedWriter:字符缓冲输出流,它只能直接给Writer系列的IO流增加缓冲功能


说明:
(1)BufferedReader比FileReader多了一次读取一行的功能
(2)提高效率(缓冲区的大小,默认是8192个字节/字符)
    为什么是更快?

    如果不使用缓冲流,每次从原文件读取 len 个字节,然后又写len 个字节到目标文件中。
    如果使用缓冲流,先从源文件缓冲一部分数据到缓冲区(内存中),然后每次从缓冲区读取len个字节,然后写len个字节到缓冲区(内存中),当缓冲区满,或者我们调用flush或close方法时,会把数据写到目标文件中。
    提高效率的秘籍在于,减少了与文件的交互次数。

    比喻:桶装水需要送水公司送桶装水过来。
       如果不使用缓冲流,相当于每次送水工从  水站 扛一桶水到尚硅谷,然后回去扛下一桶。
       如果使用缓冲流,相当于每次送水工,先在水站,用一个“车”装了很多桶,一车拉到尚硅谷,在尚硅谷的楼下,一桶一桶扛到楼上,再回去拉下一车。

    不用缓冲区,是否也可以很快呢?
    如果你力气够大,一次扛20桶。在Java中,如果一次把byte[]数组,定义的够大,也很快。
(3)缓存输出流,如果没有及时关闭,那么最后一次在缓冲区的数据,有可能在缓冲区中留存。
如果需要把数据及时写出,可以调用flush方法。

public class TestBuffered {
    @Test
    public void test05() throws IOException {
        FileWriter fw = new FileWriter("d:/1.txt");
        BufferedWriter bw = new BufferedWriter(fw);
        bw.write("hello");
        bw.flush();

        //.....

        bw.close();
    }
    @Test
    public void test04() throws IOException {
        //不使用缓冲流复制文件
        long start = System.currentTimeMillis();

        FileTools.copyBuffer("D:\\software\\IntelliJ IDEA\\ideaIC-2021.1.2.exe", "d:/idea2.exe");

        long end = System.currentTimeMillis();
        System.out.println("用时:" + (end-start));//用时:1579
    }


    @Test
    public void test03() throws IOException {
        //不使用缓冲流复制文件
        long start = System.currentTimeMillis();

        FileTools.copy("D:\\software\\IntelliJ IDEA\\ideaIC-2021.1.2.exe", "d:/idea1.exe");

        long end = System.currentTimeMillis();
        System.out.println("用时:" + (end-start));//用时:7321
    }



    @Test
    public void test02() throws IOException {
        //演示用BufferedReader辅助FileReader来读取纯文本文件
        FileReader fr = new FileReader("d:/1.txt");
        BufferedReader br = new BufferedReader(fr);//BufferedReader在FileReader增加缓冲功能

        String line;
        while((line = br.readLine()) != null){
            System.out.println(line);
        }

        br.close();
        fr.close();
    }

    @Test
    public void test01() throws IOException {
        //演示用BufferedReader辅助FileReader来读取纯文本文件
        FileReader fr = new FileReader("d:/1.txt");
        BufferedReader br = new BufferedReader(fr);//BufferedReader在FileReader增加缓冲功能

        System.out.println(br.read());//一次读取一个字符
        char[] data = new char[10];
        int len = br.read(data);
        System.out.println("len = " + len);
        System.out.println(Arrays.toString(data));

        br.close();
        fr.close();
    }
}

<4>======================================================================

转换流:在字符和字节流之间做转换用的
InputStreamReader:  把字节流转为字符流类型
            把字节流中的字节数据按照指定的编码,如果没有指定编码就默认用平台编码,进行解码,转为字符流的字符。
OutputStreamWriter: 把字节流转为字符流类型
            把字符流中的字符数据按照指定的编码,如果没有指定编码就默认用平台编码,进行编码,转为字节流的字节。

public class TestTransfer {
    @Test
    public void test07() throws IOException {
        //输出一句话到d:/1.txt文件中,这个文件是GBK
        FileOutputStream fos = new FileOutputStream("d:/1.txt");//字节流
        OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK");//字符流

        //数据的流向:  (1)先把数据write到 osw流(字符流)
        //             (2)从osw字符流中,把数据用"GBK"编码进行处理,编码为字节流的数据  写到 fos字节流中
        //             (3)从fos字节流中把数据写到 "d:/1.txt"
        osw.write("大家现在努力是为了明天挣钱");

        osw.close();
        fos.close();
    }


    @Test
    public void test06() throws IOException {
        //输出一句话到d:/1.txt文件中,这个文件是GBK
        FileOutputStream fos = new FileOutputStream("d:/1.txt");

        fos.write("大家现在努力是为了明天挣钱".getBytes("GBK"));
        //String类  byte[] getBytes(String charsetName)  编码

        fos.close();
    }

    @Test
    public void test05() throws IOException {
        //输出一句话到d:/1.txt文件中,这个文件是GBK
        FileWriter fw = new FileWriter("d:/1.txt");

        fw.write("大家现在努力是为了明天挣钱");

        fw.close();
    }

    @Test
    public void test04() throws IOException {
        //读取一个“GBK”编码的纯文本文件
        //当前平台(Java程序)是UTF-8
        FileInputStream fis = new FileInputStream("d:/1.txt");//字节流
        InputStreamReader isr = new InputStreamReader(fis, "GBK");//字符流
        BufferedReader br = new BufferedReader(isr);//字符流

        //数据的流向: "d:/1.txt" ==> fis(字节流) ==> 进行GBK解码==>isr(字符流)==>br==>程序中
        String line;
        while((line = br.readLine())!=null){
            System.out.println(line);
        }

        br.close();
        isr.close();
        fis.close();
    }

    @Test
    public void test03() throws IOException {
        //读取一个“GBK”编码的纯文本文件
        //当前平台(Java程序)是UTF-8
        FileInputStream fis = new FileInputStream("d:/1.txt");
        InputStreamReader isr = new InputStreamReader(fis, "GBK");

        char[] data = new char[10];
        int len = isr.read(data);
        System.out.println("len = " + len);
        System.out.println(new String(data,0, len));

        isr.close();
        fis.close();
    }

    @Test
    public void test02() throws IOException {
        //读取一个“GBK”编码的纯文本文件
        //当前平台(Java程序)是UTF-8
        FileInputStream fis = new FileInputStream("d:/1.txt");

        byte[] data = new byte[5];
        int len = fis.read(data);
        System.out.println("len = " + len);
        System.out.println(new String(data,0, len,"GBK"));
        //String(byte[] bytes, int offset, int length, String charsetName)  String类的解码方式

        fis.close();
    }

    @Test
    public void test01() throws IOException {
        //读取一个“GBK”编码的纯文本文件
        //当前平台(Java程序)是UTF-8
        FileReader fr = new FileReader("d:/1.txt");

        char[] data = new char[10];
        int len = fr.read(data);
        System.out.println("len = " + len);
        System.out.println(new String(data,0, len));

        fr.close();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值