JAVA文件基本操作与概念

文件的概念

狭义的文件:

存储在硬盘上的数据,以文件为单位,进行组织;文件夹也叫做"目录",也是一种特殊的文件(文件里存储的也是文件)

这章笔记的内容都是指狭义的文件

广义的文件:

操作系统负责管理软硬件资源,操作系统往往会把这些资源统一抽象成文件进行管理-----"一切皆文件"

比如,有一个网卡,就把这个网卡抽象成一个"文件",创建了特殊的文件来表示网卡;从网卡接收数据,就读取这个文件,往网卡发送数据,就写这个文件

再比如,有一个键盘,想从键盘种读取数据,也是将键盘抽象成一个"文件"(stdin),读这个文件就能读取到用户输入的内容了

绝对路径与相对路径

绝对路径是指目录下的绝对位置,直接到达目标位置,通常是从盘符开始的路径,完整的描述文件位置的路径就是绝对路径

路径之间使用\(反斜杠)分隔,当然/(斜杠)也可以,一般推荐使用/(斜杠)来分隔

相对路径首先需要一个"基准路径"(现在的位置),以基准路径为起点,往下继续走直到到达目标路径的表示方式

什么是缓冲区

我们知道 I/O 的速度是很慢的,所以,大多的 OutputStream 为了减少设备操作的次数,在写数据的时候都会将数据先暂时写入内存的一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写入设备中,这个区域一般称为缓冲区

缓冲区一般分为输入缓冲区和输出缓存区,输入缓冲区是输入设备与内存通信的缓冲区,输出缓冲区是内存与输出设备通信的缓冲区

但造成一个结果,就是我们写的数据,很可能会遗留一部分在缓冲区中。需要在最后或者合适的位置,调用 flush(刷新)操作,将数据刷到设备中

File类中的文件操作

文件操作是属于操作系统层面提供的一些API,不同的操作系统提供的API是不一样的,JAVA作为一个跨平台语言,为了统一代码,就在JVM中把不同系统的文件操作API进行了封装~~

构造File对象:

File 对象名 = new File("路径");

根据文件路径创建一个新的 File 实例,路径可以是绝对路径或者相对路径

File类当中的常用方法:

修饰符及返回值类型方法名说明
StringgetParent()返回 File 对象的父目录路径
StringgetName()返回 FIle 对象的文件名(含后缀名)/目录名
StringgetPath()返回 File 对象的文件路径(构造对象时写的啥显示啥)
StringgetAbsolutePath()返回 File 对象的绝对路径
StringgetCanonicalPath()返回 File 对象的修饰过的绝对路径
booleanexists()判断 File 对象描述的文件是否真实存在
booleanisDirectory()判断 File 对象代表的文件是否是一个目录
booleanisFile()判断 File 对象代表的文件是否是一个普通文件
booleancreateNewFile()根据 File 对象,自动创建一个空文件。成功创建后返回 true
booleandelete()根据 File 对象,删除该文件。成功删除后返回 true
voiddeleteOnExit()进程退出时,根据 File 对象,删除该文件
String[]list()返回 File 对象代表的目录下的所有文件名
File[]listFiles()返回 File 对象代表的目录下的所有文件,以 File 对象表示
booleanmkdir()创建 File 对象代表的单层目录
booleanmkdirs()创建 File 对象代表的多层目录
booleanrenameTo(File dest)传递一个File对象,进行文件改名
booleancanRead()判断用户是否对文件有可读权限
booleancanWrite()判断用户是否对文件有可写权限

文本文件与二进制文件

数据文件被分为文本文件或者二进制文件

数据在内存中以二进制的形式存储,如果不加转换的输出到硬盘,就是二进制文件

如果要求在硬盘上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件

文件内容的读写操作

把硬盘上的数据往内存上面写就是输入

把内存上的数据往硬盘上面写就是输出

文件内容的读写也叫做"流"(stream),计算机中的流其实是一种信息的转换,把文件内容的读写操作比喻成水流,java标准库在"流"的概念上,提供了一组类,完成文件内容的读写操作~~

读写文件分为两种:一种是字节流(按字节读和写),一种是字符流(按字符读和写)

InputStream和OutputStream是字节流的,Reader和Writer是字符流的,Scanner和PrintWriter也是字符流的

打开文件以后一定要记得close()文件,不然会出现文件资源泄露的情况!!!

字节流InputStream:

读数据,把数据从硬盘读到内存中,InputStream 只是一个抽象类,要使用还需要具体的实现类,使用FileInputStream

修饰符及返回值类型方法名说明
intread()读取一个字节的数据,返回 -1 代表已经完全读完了
intread(byte[] b)把读到的内容放到字节数组b中,返回实际读到的字节数;返回 -1 代表以及读完了
intread(byte[] b, int off, int len)从字节数组b下标为off位置开始读len个字节,返回实际读到的字节数;返回 -1 代表以及读完了
voidclose()关闭字节流(关闭文件)

FileInputStream:

InputStream的具体实现类

方法名说明
FileInputStream(File file)利用 File 构造文件输入流(打开文件)
FileInputStream(String name)利用文件路径构造文件输入流(打开文件)
public class Test2 {
    public static void main(String[] args) throws IOException {
        //打开文件
        InputStream inputStream = new FileInputStream("bbb.txt");
        //读取文件内容
        while (true) {
            int b = inputStream.read();
            if (b == -1) {
                break;
            }
            System.out.println(b);
        }
        //关闭文件
        inputStream.close();
    }
}

字节流OutputStream:

写数据,把数据从内存写入到硬盘中,OutputStream只是一个抽象类,要使用还需要具体的实现类,使用FileOutputStream

使用OutputStream写文件的时候,只要打开文件成功,就会把文件原有内容清空~~如果文件不存在会自动创建

修饰符及返回值类型方法名说明
voidwrite(int b)写入一个字节的数据
voidwrite(byte[] b)把字节数组里的所有内容都写到文件中
intwrite(byte[] b, int off, int len)把b字节数组从下标off位置开始写,写len个字节
voidclose()关闭字节流(关闭文件),也有清空缓冲区的作用
voidflush()重要:我们知道 I/O 的速度是很慢的,所以,大多的 OutputStream 为了减少设备操作的次数,在写数据的时候都会将数据先暂时写入内存的一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写入设备中,这个区域一般称为缓冲区。但造成一个结果,就是我们写的数据,很可能会遗留一部分在缓冲区中。需要在最后或者合适的位置,调用 flush(刷新)操作,将数据刷到设备中。

FileOutputStream:

OutputStream的具体实现类

方法名说明
FileOutputStream(File file)利用 File 构造文件输出流(打开文件)
FileOutputStream(String name)利用文件路径构造文件输出流(打开文件)
public class Test1 {
    public static void main(String[] args) throws IOException {
        //打开文件
        OutputStream outputStream = new FileOutputStream("./bbb.txt");
        //OutputStream只要打开文件成功,就会把文件原有内容清空,如果文件不存在会自动创建
        outputStream.write(97);
        outputStream.write(98);
        outputStream.write(99);
        //关闭文件
        outputStream.close();
    }
}

字符流Reader:

读数据,把数据从硬盘读到内存中,Reader 只是一个抽象类,要使用还需要具体的实现类,使用FileReader

修饰符及返回值类型方法名说明
intread()读取一个字符的数据,返回 -1 代表已经完全读完了
intread(char[] b)把读到的内容放到字符数组b中,返回实际读到的字符数;返回 -1 代表以及读完了
intread(char[] b, int off, int len)从字符数组b下标为off位置开始读len个字符,返回实际读到的字符数;返回 -1 代表以及读完了
voidclose()关闭字符流(关闭文件)

字符流FileReader:

Reader的具体实现类

方法名说明
FileReader(File file)利用 File 构造文件输入流(打开文件)
FileReader(String name)利用文件路径构造文件输入流(打开文件)
public class Test2 {
    public static void main(String[] args) throws IOException {
        //打开文件
        Reader reader = new FileReader("./bbb.txt");
        //读取文件内容
        while (true) {
            int ret = reader.read();
            if (ret == -1) {
                break;
            }
            char ch = (char) ret;
            System.out.println(ch);
        }
        //关闭文件
        reader.close();
    }
}

Writer:

写数据,把数据从内存写入到硬盘中,Writer只是一个抽象类,要使用还需要具体的实现类,使用FileWriter

使用Writer写文件的时候,只要打开文件成功,就会把文件原有内容清空~~如果文件不存在会自动创建

修饰符及返回值类型方法名说明
voidwrite(int b)写入一个字符的数据
voidwrite(char[] b)把字符数组里的所有内容都写到文件中
voidwrite(String b)写入b字符串数据
intwrite(char[] b, int off, int len)把b字符数组从下标off位置开始写,写len个字符
intwrite(String b,int off,int len)把b字符串从下标off位置开始写,写len个字符
voidclose()关闭字符流(关闭文件),也有清空缓冲区的作用
voidflush()重要:我们知道 I/O 的速度是很慢的,所以,大多的 OutputStream 为了减少设备操作的次数,在写数据的时候都会将数据先暂时写入内存的一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写入设备中,这个区域一般称为缓冲区。但造成一个结果,就是我们写的数据,很可能会遗留一部分在缓冲区中。需要在最后或者合适的位置,调用 flush(刷新)操作,将数据刷到设备中。

FileWriter:

Writer的具体实现类

方法名说明
FileWriter(File file)利用 File 构造文件输出流(打开文件)
FileWriter(String name)利用文件路径构造文件输出流(打开文件)
public class Test3 {
    public static void main(String[] args) throws IOException {
        //打开文件
        Writer writer = new FileWriter("./bbb.txt");
        //Writer只要打开文件成功,就会把文件原有内容清空,如果文件不存在会自动创建
        writer.write("hello world");
        //关闭文件
        writer.close();
    }
}

Scanner:

使用字符流进行读操作的时候,还可以使用Scanner来进行读取~~

public class Test4 {
    public static void main(String[] args) throws IOException {
        //打开文件
        InputStream inputStream = new FileInputStream("./bbb.txt");
        //使用Scanner作为一个字符流对象(传递字节流对象)
        Scanner scanner = new Scanner(inputStream);
        while (scanner.hasNext()) {
            System.out.println(scanner.next());
        }
        //关闭文件
        inputStream.close();
    }
}

PrintWriter:

使用字符流进行写操作的时候,还可以使用PrintWriter来进行写操作~~

public class Test5 {
    public static void main(String[] args) throws IOException {
        //打开文件
        OutputStream outputStream = new FileOutputStream("./bbb.txt");
        //使用PrintWriter作为一个字符流对象(传递字节流对象)
        PrintWriter writer = new PrintWriter(outputStream);
        writer.printf("a = %d\n",10);
        writer.println();
        writer.print("abc");
        //关闭文件
        outputStream.close();
    }
}

所有代码都需要考虑close是否一定能被执行的问题:

public class Test6 {
    public static void main(String[] args) throws IOException {
        OutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream("./bbb.txt");
            PrintWriter writer = new PrintWriter(outputStream);
            writer.printf("a = %d\n",10);
            writer.println();
            writer.print("hello world");
        }finally {
            outputStream.close();
        }
    }
}
​
-----------------------------------------------------------------------------------------
​
public class Test6 {
    public static void main(String[] args) throws IOException {
        try(OutputStream outputStream = new FileOutputStream("./bbb.txt")) {
            PrintWriter writer = new PrintWriter(outputStream);
            writer.printf("a = %d\n",10);
            writer.println();
            writer.print("hello world");
        }
    }
}

文件操作的一些实例

一、扫描指定目录,并找到名称中包含指定字符的所有普通文件(不包含目录),并且后续询问用户是否要删除该文件~~

操作:

1、先让用户输入要扫描的路径+要查找的词

2、遍历目录,找到名字匹配的文件

3、询问用户是否删除

public class Test7 {
    public static void main(String[] args) throws IOException {
        //从键盘输入目录路径
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要扫描的路径: ");
        File rootDir = new File(scanner.next());
        //判断目录路径是否存在
        if (!rootDir.isDirectory()) {
            System.out.println("您输入的目录不存在");
            return;
        }
        //从键盘输入关键词
        System.out.println("请输入要搜索的关键词: ");
        String toDelete = scanner.next();
        //遍历目录
        scanDir(rootDir,toDelete);
    }
​
    //借助这个方法进行递归遍历
    public static void scanDir(File rootDir, String toDelete) throws IOException {
        File[] files = rootDir.listFiles();
        if (files == null) {
            //说明rootDir是一个空的目录
            return;
        }
        //rootDir非空,循环遍历每个元素
        for (File f : files) {
            //当前rootDir是目录
            if (f.isDirectory()) {
                //递归里面的内容
                scanDir(f,toDelete);
            }else {
                //不是目录,是普通文件,判定文件名是否符合要求,是否要进行删除
                checkDelete(f,toDelete);
            }
        }
    }
​
    //删除操作
    public static void checkDelete(File f, String toDelete) throws IOException {
        if (f.getName().contains(toDelete)) {
            System.out.println("该单词" + toDelete + "被" + 
                    f.getCanonicalPath() + "包含了" + ",是否要删除? (Y/N)");
            Scanner scanner = new Scanner(System.in);
            String choice = scanner.next();
            if (choice.equals("Y") || choice.equals("y")) {
                f.delete();
            }
        }
    }
}

二、普通文件的复制

操作:把第一个文件打开,把里面的内容逐个字节的读取出来,写入到第二个文件中即可~~

public class Test8 {
    public static void main(String[] args) throws IOException {
        //1.先输入要复制哪个文件(源文件),以及把这个文件复制到哪里去(目标文件)~~
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入源文件: ");
        //srcFile 形如 d:/cat.jpg
        File srcFile = new File(scanner.next());
        System.out.println("请输入目标文件: ");
        //destFile 形如 d:/cat2.jpg
        File destFile = new File(scanner.next());
        if (!srcFile.isFile()) {
            System.out.println("输入的源文件有误");
            return;
        }
        if (!destFile.getParentFile().isDirectory()) {
            System.out.println("输入的目标文件有误");
            return;
        }
        //2.打开源文件,按照字节读取内容,再依次写入到目标文件
        try (InputStream inputStream = new FileInputStream(srcFile);
        OutputStream outputStream = new FileOutputStream(destFile)){
            //读src的每个字节,写入到dest中
            while (true) {
                int ret = inputStream.read();
                if (ret == -1) {
                    break;
                }
                outputStream.write(ret);
            }
        }
    }
}

三、扫描指定目录,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录)

操作:

1、先让用户输入要扫描的路径+要查找的词

2、遍历目录,找到文件名匹配与内容匹配的文件

public class Test9 {
    public static void main(String[] args) throws IOException {
        //1.输入路径和要查询的关键词
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要扫描的路径: ");
        File rootDir = new File(scanner.next());
        System.out.println("请输入要查询的词: ");
        String toFind = scanner.next();
        //2.递归的扫描目录
        scanDir(rootDir,toFind);
    }
​
    public static void scanDir(File rootDir, String toFind) throws IOException {
        File[] files = rootDir.listFiles();
        if (files == null) {
            return;
        }
        for (File f : files) {
            if (f.isDirectory()) {
                scanDir(f,toFind);
            }else {
                checkFile(f,toFind);
            }
        }
    }
​
    public static void checkFile(File f, String toFind) throws IOException {
        //1.先检查文件名
        if (f.getName().contains(toFind)) {
            System.out.println(f.getCanonicalPath() + " 文件名中包含 " + toFind);
        }
        //2.再检查文件内容
        try (InputStream inputStream = new FileInputStream(f)){
            StringBuilder stringBuilder = new StringBuilder();
            Scanner scanner = new Scanner(inputStream);
            while (scanner.hasNextLine()) {
                stringBuilder.append(scanner.nextLine() + "\n");
            }
            if (stringBuilder.indexOf(toFind) > -1) {
                System.out.println(f.getCanonicalPath() + " 文件内容包含 " + toFind);
            }
        }
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值