java文件和流的相关知识点总结

文件类File

Java中的File类,表示本地硬盘中的文件(文件和目录)的一个类。

通过这个类创建的对象,可以操作对应的文件。

构造方法

常用构造方法说明
File(String pathName)根据文件的完整路径创建File对象
File(String parent,String child)根据文件的父目录路径和自身路径创建File对象
File(File parent,String child)根据文件的父目录对应的File对象和自身路径创建File对象
//如想要表示 “F:\221001\笔记\面向对象部分回顾.pdf”  这个文件

//File(String pathName)
File file1 = new File("F:\\221001\\笔记\\面向对象部分回顾.pdf");

//File(String parent,String child)
File file2 = new File("F:\\221001\\笔记", "面向对象部分回顾.pdf");

//File(File parent,String child)
File parent = new File("F:\\221001\\笔记");
File file3 = new File(parent, "面向对象部分回顾.pdf");

//file1、file2、file3都表示同一个文件

常用方法

常用方法说明
exists()判断文件是否存在
isFile()判断是否为文件
isDirectory()判断是否为目录
getName()获取文件名
getPath()获取文件相对路径
getAbsolutePath()获取文件绝对路径
getParent()获取父目录的名称
getParentFile()获取父目录对象
lastModified()获取最后一次修改时间对应的毫秒数
length()获取文件所占字节
isHidden()判断文件是否隐藏
delete()删除文件或空目录
renameTo(File newFile)将原文件重命名且移动到指定目录
mkdir()创建目录
list()获取某个目录下的第一层子文件的名称的数组
listFiles()获取某个目录下的第一层子文件对象的数组

斐波那契数列

package com.hqyj.FileTest;

public class Test2 {
    public static void main(String[] args) {
        //兔子问题
        //有一对兔子在第三个月开始,每个月都能生一对小兔子
        //如果所有兔子不死亡,且每次生下的都是一雌一雄,问10个月后共有多少对兔子
        //1月    2月  3月  4月  5月  6月  7月  8月  9月  10月
        //1     1    2    3    5   8    13   21   34   55
        //斐波那契数列
        //f(n)=f(n-1)+f(n-2)  n>2
        Test2 t = new Test2();
        System.out.println(t.f(20));
    }

    /*
     * 递归方法
     * */
    public int f(int n) {
        if (n > 2) {
            return f(n - 1) + f(n - 2);
        }
        return 1;
    }
}

递归遍历文件夹

package com.hqyj.FileTest;

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

public class Test3 {
    //查看某个目录下的所有文件
    public static void main(String[] args) {

        File source = new File("E:\\adobe");


        Test3 t = new Test3();
        t.fun(source);

    }

    /*
     * 递归遍历文件夹
     * */
    public void fun(File source) {
        //输出某个目录中超过3个月未使用且大于500MB的文件
        /*
        long start = source.lastModified();
        long end = System.currentTimeMillis();
        if ((end - start) / 1000 / 3600 / 24 > 90 && source.length() / 1024 / 1024 > 500) {
            System.out.println(source.getName() + "\t" + new Date(source.lastModified()) + "\t" + source.length() / 1024 / 1024);
        }*/

        //判断是否为目录
        if (source.isDirectory()) {
            //将其展开
            for (File child : source.listFiles()) {
                //因为子文件有可能是目录,继续调用本方法
                fun(child);
            }
        }
    }
}

IO

I:Input输入

O:Output输出

流Stream

在Java中,流用于表示计算机硬盘与内存之间传输数据的通道。

内存中的数据存入到硬盘中,称为写write,也称为输出Output

硬盘中的数据存入到内存中,称为读read,也称为输入Input

流的分类

Java中将流定义为类,以对象的形式表现流。流有"四大家族",是所有流的父类。

字节输入流InputStream

FileInpuStreamObjectInputStream

字节输出流OutputStream

FileOutputStreamObjectOutputStream

字符输入流Reader

FileReader、BufferedReader、OutputStreamWriter

字符输出流Writer

FileWriter、BufferedWriter、InputStreamReader

按方向分类

  • 输入流:InputStream、Reader

    • 将硬盘中的数据读取到内存中
  • 输出流:OutputStream、Writer

    • 将内存中的数据写入到硬盘中

按类型分

  • 字节流:InputStream、OutputStream
    • 读写非文本类型文件。如图片、音视频、其他文件等。
  • 字符流:Reader、Writer
    • 读写纯文本类型文件。如txt、md等

如要将硬盘中某个txt文件中的内容读取到程序中,使用Reader

如要将硬盘中的某个图片读取到程序中,使用InputStream

如要将程序中的文本写入到硬盘中为txt类型文件时,使用Writer

如要将程序中的数据写入到硬盘中为非文本文件时,使用OutputStream

流的四个父类的特点

  • 这四个父类都是在java.io包下,都是抽象类,不能直接创建其对象,使用其子类创建对象
  • 这四个父类中都定义了close()方法,用于关闭流对象,释放资源
  • 输入流(InputStream和Reader)都有read()方法读取数据到内存中,输出流都有write()方法写入数据到硬盘中
  • 输出流(OutputStream和Writer)都有flush()方法,用于将流中的数据冲刷到硬盘中
    • 在使用输出流对象时,一定要调用flush()或close()方法后,才能真正将数据写入到硬盘中
  • 所有的流中,以Stream结尾,都是字节流,数据以字节传输;以Reader或Writer结尾的,都是字符流,数据以字符传输
  • 读取硬盘中的数据,使用输入流,读取的文件必须存在;将数据写入到硬盘中,使用输出流,文件可以不存在,但父目录必须存在。
  • 读入或写入文本时,使用字符流;读取或写入非文本时,使用字节流

FileInputStream文件字节输入流(掌握)

按字节读取硬盘中的文件。

构造方法

常用构造方法说明
FileInputStream(String pathName)根据文件名创建流对象
FileInputStream(File file)根据文件对象创建流对象

常用方法

常用方法说明
read()读取一个字节,返回读取到的字节
read(byte[] bytes)按字节数组读取,返回读取到的字节数量,读取到的内容保存在字节数组中
close()关闭流对象

FileOutputStream文件字节输出流(掌握)

按字节将内存中的数据写入到硬盘中。

构造方法

常用构造方法说明
FileOutputStream(String pathname)根据文件名创建输出流对象,写入时覆盖原内容
FileOutputStream(String pathname,boolean append)根据文件名创建输出流对象,第二个参数为true,写入时追加在原内容之后
FileOutputStream(File file)根据文件对象创建输出流对象,写入时覆盖原内容
FileOutputStream(File file,boolean append)根据文件对象创建输出流对象,第二个参数为true,写入时追加在原内容之后

常用方法

常用方法作用
write(int i)写入一个指定字节
write(byte[] bytes)写入一个字节数组
write(byte[] bytes,int off,int len)写入字节数组中从off开始的len个字节
flush()将流中的数据冲刷到硬盘中
close()关闭流对象

使用FileInputStream和FileOutputStream读写时的注意事项

  • 在通过FileInputStream对象使用read(byte[] bytes)方法时,每次读取指定数组的字节,将读取到的字节保存在字节数组中,该方法返回读取到的字节数量。如果最后一次读取的字节数不足字节数组的大小时,只会将读取到内容覆盖数组中最前的几个元素。所以会导致读取到的内容多于实际内容。

  • 在通过FileOutputStream对象使用write(byte[] bytes)方法时,会将字节数组中的所有内容写入到输出流中,在最后一次写入时,可能会写入多余的内容。所以在写入时,最好使用write(byte[] bytes,int off,int lef)方法,表示将字节数组中的内容,从off开始写入len个。

    如有word.txt文件,其中保存aaabbbccc

    FileInputStream fis = new FileInputStream("d:/word.txt");
    FileOutputStream fos = new FileOutputStream("d:/copy.txt");
    
    byte[] bytes = new byte[4];
    //第一次读取4个字节,即aaab,count为4
    int count=fis.read(bytes);
    //写入数组中的全部内容
    fos.write(bytes);
    //第二次读取4个字节,即bbcc,count为4
    count=fis.read(bytes);
    //写入数组中的全部内容
    fos.write(bytes);
    //第三次读取1个字节c,覆盖数组中的第一个元素,即数组现在为cbcc,count为1
    count=fis.read(bytes);
    //写入数组中的全部内容
    fos.write(bytes);//最终会写入aaabbbcccbcc
    fos.write(bytes,0,count);//这样最后一次只会写入实际读取到的c
    
    fos.close();
    fis.close();
    

使用FileInputStream和FileOutputStream实现单文件的复制

package com.hqyj.IOTest;

import java.io.*;

public class CopyFile {
    public static void main(String[] args) throws IOException {
        //定义原文件和目标文件
        File source = new File("F:\\221001\\录屏\\FileInputStream和FileOutputStream.mp4");
        File target = new File("F:\\221001\\copy.mp4");

        //定义文件字节输入流,用于读取原文件
        FileInputStream fis = new FileInputStream(source);
        //定义文件字节输出流,用于写入文件
        FileOutputStream fos = new FileOutputStream(target);


        /*
        //调用无参的read()方法,表示读取一个字节,返回读取到的字节
        int read = fis.read();
        //如果能读取到内容
        while (read > -1) {
            //将读取到的内容写入到文件中
            fos.write(read);
            //继续读取
            read = fis.read();
        }
        */

        //定义一个字节数组,大小为8MB
        byte[] bytes = new byte[1024 * 1024 * 8];

        //按字节数组读取,返回读取到的字节数量
        int count = fis.read(bytes);
        //循环读取写入
        while (count > -1) {
            //将读取的字节数组写入到文件中
            // fos.write(bytes);//如果调用该方法,最后一次会多写入上一次残留的数据
            fos.write(bytes,0,count);//如果调用该方法,实际读取到了多少字节就写入多少
            count = fis.read(bytes);
        }


        fis.close();
        fos.close();

        if (target.exists()) {
            System.out.println("复制成功");
        }

    }
}

文件夹的复制

package com.hqyj.IOTest;

import java.io.*;

public class CopyDirectory {
    public static void main(String[] args) {


        /*File source = new File("F:\\221001\\录屏\\流的基本概念.mp4");
        File target = new File("F:\\221001\\copy.mp4");
        copyFile(source, target);*/

        File source = new File("F:\\221001\\笔记");
        File target = new File("F:\\221001\\笔记副本");
        /*
         * source    F:\221001\笔记
         * target    F:\221001\笔记副本
         * 1.调用copyDir方法,判断发现source是一个文件夹,创建目标文件夹target:“F:\221001\笔记副本”
         * 2.遍历source,如其中有xxx.md文件,即child
         * 此时的source是F:\221001\笔记\xxx.md,即child
         * 此时的target是F:\221001\笔记副本\xxx.md,用File(File parent,String child)构造方法表示这个目标文件
         * 所以创建File newTarget = new File(target,child.getName())
         *
         * */

        copyDir(source, target);
    }


    /*
     * 定义复制文件夹的方法
     * */
    public static void copyDir(File source, File target) {
        //如果是文件,调用单文件复制的方法
        if (source.isFile()) {
            copyFile(source, target);
        } else {//如果是文件夹
            //创建要复制的目标文件夹
            target.mkdir();
            //展开原文件夹
            for (File child : source.listFiles()) {
                //定义复制后的新目标文件
                //如source为F:\221001\笔记\day1.md时,递归调用的target为F:\221001\笔记副本\day1.md
                File newTarget = new File(target, child.getName());//这里使用File(File parent,String child)构造方法创建target对象
                //递归调用的原文件依然是当前遍历出来的子文件,目标文件就是最终复制的F:\221001\笔记副本\day1.md
                copyDir(child, newTarget);
            }
        }
    }


    /*
     * 定义单文件复制的方法
     * */
    public static void copyFile(File source, File target) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            //创建用于输入输出的流对象
            fis = new FileInputStream(source);
            fos = new FileOutputStream(target);
            //定义字节数组
            byte[] bytes = new byte[1024 * 1024 * 8];
            //按数组读取
            int count = fis.read(bytes);
            while (count != -1) {
                fos.write(bytes, 0, count);
                count = fis.read(bytes);
            }
        } catch (FileNotFoundException e) {
            System.out.println("文件不存在" + e);
        } catch (IOException e) {
            System.out.println("读写异常" + e);
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                System.out.println("关闭流对象异常" + e);
            }
        }
    }
}

断点调试执行细节

FileReader文件字符输入流

按字符读取文件。

构造方法

常用构造方法说明
FileReader(String fileName)根据文件名创建文件字符输入流对象
FileReader(File file)根据文件对象创建文件字符输入流对象

常用方法

常用方法作用
ready()判断是否还有下一个字符
read()读取下一个字符,返回读取到的字符
read(char[] chars)按字符数组读取,返回读取到的字符数量,读取到的字符保存在字符数组中
close()关闭流对象

FileWriter文件字符输出流

按字符写入文件。

构造方法

常用构造方法作用
FileWriter(String fileName)按文件名创建字符输出流对象,覆盖写入
FileWriter(String fileName,boolean append)按文件名创建字符输出流对象,如果append为true,表示追加写入
FileWriter(File file)按文件对象创建字符输出流对象,覆盖写入
FileWriter(File file,boolean append)按文件对象创建字符输出流对象,如果append为true,表示追加写入

常用方法

常用方法作用
write(String str)按字符串写入
flush()将流中的数据冲刷到硬盘中的文件,必须调用该方法或close方法后,才能真正写入
close()关闭流对象

BufferedReader缓冲字符输入流(掌握)

自带缓冲区(字符数组)的字符输入流。默认字符数组大小为8192,每次最多读取8192个字符。

在读取纯文本文件(txt或md)时,首选该类。

构造方法

常用构造方法作用
BufferedReader(Reader in)创建一个带有缓冲区(大小为8192的char数组)的字符输入流对象,参数为Reader类型对象,Reader是抽象类,所以实际参数为Reader的子类,如FileReader,在FileReader对象中定义要读取的文件
BufferedReader(Reader in,int size)创建一个指定缓冲区(字符数组)大小的字符输入流对象

常用方法

常用方法作用
ready()判断是否还有字符
readLine()读取整行字符
close()关闭流对象

读取文本练习

package com.hqyj.ReaderAndWriter;

import java.io.*;

public class Test2 {
    public static void main(String[] args) throws IOException {

        /*
        File file = new File("F:\\221001\\笔记\\Java基础回顾.md");
        //FileReader(File file)
        Reader fr = new FileReader(file);
        //BufferedReader(Reader in)
        BufferedReader br = new BufferedReader(fr);
        */

        //创建带有缓冲区的字符输入流对象
        BufferedReader br = new BufferedReader(new FileReader("F:\\221001\\笔记\\Java基础回顾.md"));
        //循环判断是否还有字符
        while (br.ready()) {
            //读取整行
            System.out.println(br.readLine());
        }
        //关闭最大的流对象即可
        br.close();
    }
}

BufferedWriter缓冲字符输出流(掌握)

自带缓冲区(字符数组)的字符输出流

构造方法

常用构造方法说明
BufferedWriter(Writer writer)创建一个自带缓冲区的字符输出流对象,参数为一个Writer对象,Writer是一个抽象类,实际参数为Writer的子类,如FileWriter,在FileWriter中定义要将输入写入的目标文件
BufferedWriter(Writer writer,int size)创建一个指定缓冲区大小的字符输出流对象

常用方法

常用方法作用
write(String str)写入字符串
newLine()换行
flush()冲刷流中的数据到硬盘
close()关闭流对象

写入文本练习

package com.hqyj.ReaderAndWriter;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.logging.SimpleFormatter;

public class Test3 {
    public static void main(String[] args) throws IOException {

        File file = new File("221001.txt");
        //创建缓冲字符输入流对象,读取文本
        BufferedReader br = new BufferedReader(new FileReader(file));
        //创建集合,保存读取到的姓名
        ArrayList<String> list = new ArrayList<>();
        //循环读取文件中的所有字符
        while (br.ready()) {
            String name = br.readLine();
            list.add(name);
        }
        //关闭
        br.close();
        //打乱集合中的元素
        Collections.shuffle(list);


        //创建日期字符串
        String today = new SimpleDateFormat("yyyy.MM.dd").format(new Date());
        //创建缓冲字符输出流,用于写文本,文件名为"日期+作业情况.txt",如果每次都是新建,这样写
        // BufferedWriter bw = new BufferedWriter(new FileWriter(today + "作业情况.txt"));
        //如果要追加,在new FileWriter("文件名",true)设置
        BufferedWriter bw = new BufferedWriter(new FileWriter(today + "作业情况.txt",true));
        //写入字符串
        bw.write("姓名\t\t是否完成");
        //换行
        bw.newLine();


        Scanner sc = new Scanner(System.in);
        //随机3个人
        for (int i = 0; i < 3; i++) {
            String name = list.get(i);
            System.out.println(name + "完成情况:");
            String str = sc.next();
            //写入读取到的内容
            bw.write(name + "\t\t" + str);
            //换行
            bw.newLine();
        }

        bw.close();
    }
}

ObjectOutputStream对象字节输出流(序列化)(掌握)

序列化:将对象转换为文件的过程

被序列化的对象,必须要实现Serializable接口。

这个接口是一个特殊的接口,没有定义任何方法,只是给该类加上标记,表示该类可以被序列化

构造方法

构造方法说明
ObjectOutputStream(OutputStream os)创建一个对象字节输出流对象,参数为一个字节输出流对象,由于OutputStream是抽象类,所以使用其子类,如FileOutputStream对象,在其中定义要写入的文件

常用方法

常用方法作用
writeObject(Object obj)将一个对象写入到本地文件中
close()关闭流对象

ObjectInputStream对象字节输入流(反序列化)(掌握)

反序列化:将文件转换为对象的过程

构造方法

常用构造方法说明
ObjectInputStream(InputStream is)创建一个对象字节输入流对象,参数为一个字节输入流对象,由于InputStream是抽象类,所以使用其子类,如FileInputStream对象,在其中定义要读取的文件

常用方法

常用方法作用
readObject()读取序列化后的文件,返回类型为Object
close()关闭流对象

序列化和反序列化案例

Person类,实现Serializable接口

package com.hqyj.ObjectStream;

import java.io.Serializable;
/*
* 如果希望该类的对象能序列化,写入对象到本地,必须要实现Serializable接口
* Serializable接口中没有任何方法,是一个标记接口,表示该类的对象可以被序列化
* */
public class Person implements Serializable {
    private String name;
    private int age;
    private String sex;

 	//省略getter/setter和toString()
}

Main类

package com.hqyj.ObjectStream;

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

public class Test1 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Person p1 = new Person("王海", 22, "男");
        Person p2 = new Person("赵敏", 24, "女");
        Person p3 = new Person("刘涛", 21, "女");
        ArrayList<Person> list = new ArrayList<>();
        list.add(p1);
        list.add(p2);
        list.add(p3);

        //创建OutStream的实现类,设置写入的文件路径
        OutputStream os = new FileOutputStream("F:\\221001\\person.p");
        //创建对象输出字节流,参数为OutStream类型
        ObjectOutputStream oos = new ObjectOutputStream(os);
        //调用writeObject(Object obj)方法,将对象写入到硬盘中(序列化)
        oos.writeObject(list);

        oos.close();

        //创建对象输入字节流,将上一步保存的文件进行反序列化
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("F:\\221001\\person.p"));

        //使用readObject()方法,将写入的文件进行读取(反序列化)
        ArrayList<Person> pList = (ArrayList<Person>) ois.readObject();

        for (Person person : pList) {
            System.out.println(person);
        }
        ois.close();
    }
}

转换流

实际属于字符流,作用为将一个字节流对象转换为字符流对象

OutputStreamWriter

将字节输出流转换为字符输出流

InputStreamReader

将字节输入流转换为字符输入流

转换流的使用

如果只提供了一个字节流,但要向其中写入或读取字符时,就可以使用转换流将字节流转换为字符流。

使用字符流读写字符时比字节流更方便。

//假如只提供一个字节输出流对象
FileOutputStream fos = new FileOutputStream("文件路径");
//fos.write(97);//这时如果写入数据,只能按字节写入,不方便

//使用转换流,将字节流对象fos转换为字符流对象
Writer writer = OutputStreamWriter(fos);
//将字符流对象writer包装成缓冲字符流对象
BufferedWriter bw = new BufferedWriter(writer);
bw.write("hello你好");
bw.newLine();

bw.close();


//只提供字节输入流对象
FileInputStream fis = new FileInputStream("221001.txt");

// fis.read()每次只能读取一个字节
//将字节流转换为字符流
Reader reader = new InputStreamReader(fis);
//创建缓冲字符流,将字符流包装为缓冲流
BufferedReader br = new BufferedReader(reader);
//整行读取
while (br.ready()) {
    System.out.println(br.readLine());
}
br.close();
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值