【JavaEE】文件操作

目录

前言

一、什么是文件

二、树形结构组织和目录

三、文件路径

四、文件类型

五、文本权限

六、java中操作文件

File中常见属性

File构造方法

File常用方法

七、相关方法使用案例

示例一:观察get方法的差异

[示例二 :文件的创建](#示例二 :文件的创建)

示例三:文件的删除

示例四:打印目标目录内的所有文件

示例五:打印项目内所有的文件路径

示例六:创建目录

示例七:文件/文件夹的改名(剪切)

示例八:查看文件的权限


前言

文件在计算机中使用非常广泛,我们在日常生活中都会接触到,文件不仅限于硬盘上的文件,还有计算机上的很多硬件设备,例如键盘,显示屏等,以及软件资源,在操作系统中都可以视为"文件"。

一、什么是文件

从狭义的角度来说,文件就是特指硬盘上的文件(以及保存文件的目录)。针对硬盘架这种持久化存储的I/O设备,当我们想要进行数据存储时,往往不是保存成一个整体,而是独立成一个个的党委进行保存,这个独立的单位就被抽象成文件的概念,就像办公桌上一份份真实的文件一般。

从广义的角度来说,计算机上的很多硬件设备,软件资源,在操作系统中都会被视为是"文件"

文件除了有数据内容之外,还有一部分信息,例如文件名、文件类型、文件大小等并不作为文件的数据而存在,我们把这部分信息可以视为文件的元信息。看下图:

硬盘和内存的对比:

  1. 硬盘存储空间大,内存小
  2. 硬盘速度慢,内存快
  3. 硬盘成本低,内存高
  4. 硬盘能持久化存储,而内存在断电后就丢失数据

硬盘之所以慢,主要是跟它硬件的物理结构有关。

其中磁盘就是用来存储数据的介质,当通电之后,盘片就会快速旋转(7200r/min)。

当我们想要读取数据的时候,是通过磁头来读写数据的。如果是顺序读写,那么效率就会比较高,若是随机读写,效率会比较低。(磁头会指哪打哪)

上述是针对机械硬盘,不过我们现在大部分用的都是固态硬盘。

固态硬盘和机械硬盘的物理结构不同,类似于"内存",通过大规模的集成电路来实现的存储功能。固态硬盘的速度比机械硬盘的要快10-20倍。

二、树形结构组织和目录

随着文件的增多,那么操作系统中是如何进行管理文件的呢?

在Linux系统中,文件系统采用的是树形结构,也可以称为层级目录结构。整个文件系统只有一个根目录,所有的文件和目录都从根目录开始组织和管理。根目录下可以有多个子目录,每个子目录又可以包含其他子目录和文件。

在Windows上的文件系统也采用了树形目录结构,这种结构以根目录为起点,向下分支形成各级子目录,每个子目录又可以包含更深一层的子目录,形成一个类似树形的结构。

三、文件路径

既然知道了文件如何在文件系统中存储的,那么我们如何在文件系统中找到我们所想要的文件呢?

从树形结构的角度来看,树中的每个节点都可以被一条从根开始,一直到达节点的路径锁描述,而这种描述方式就被称为文件的绝对路径(absolute path)。

除了可以从根节点进行路径的描述,我们可以从任意节点出发,进行路径的描述,而这种描述方式就被称为相对路径(relative path),相对于当前所在节点的一条路径。

例如:在Windows上此时的当前目录为"D\documents",那么相对路径就是".\text.txt",找到名为"text.txt"文件的绝对路径就是"D\documents\text.txt"。

. 表示当前目录,. .表示当前目录的上一级目录

在Liunx中,我们是使用**(/)斜杠作为分隔符,**从根目录开始一直到具体文件或目录。例如,路径"/home/user/documents/text.txt"这是说明从根目录出发,进入home目录,在进入documents目录,最后找到文件名为text.txt的文本。

在Windows中,我们可以使用反斜杠(\)或者斜杠(/)来作为分隔符。从根文件夹一直找到目标文件或者文件夹。例如"D:\documents\text.txt"表示从D盘文件夹出发,进入documents文件夹中,找到文件名为text.txt的文本文件。

在Windows中,我们习惯使用反斜杠(\),在某些情况可能需要转移操作。

四、文件类型

即使是普通文件,根据其保存数据的不同,也经常被分为不同类型,我们一般简单的划分为文本文件和二进制文件,分别指代保存被字符集(UTF8、GBK)编码的文本和按照标准格式保存的非被字符集编码的文件

文本文件和二进制文件的区别:

  • 存储方式:文本文件采用定长的编码方式,每个字符占固定的比特位数,而二进制文件采用变长编码方式,由一组0和1的二进制数组组成,多少个比特位由一个值具体的应用决定。
  • 编码方式:文本文件是基于字符编码的文件,常见的编码有ASCII编码、UNICODE编码等。而二进制文件时基于值编码的文件,由二进制数组0和1组成,不存在统一的字符编码。
  • **用途:**文本文件主要用于存储和处理文本数据,如文本编辑、排版、程序源代码等。二进制文件主要用于存储和处理二进制数据,如图像、音频、视频、可执行文件等。
  • **文件扩展名:**文本文件的扩展名一般是.txt、.doc、.docx、.java等,而二进制文件的扩展名则根据具体的文件类型而定,如.jpg、.mp3、.avi等。

如何判断一个文件是文本文件还是二进制文件?

我们可以通过记事本来进行查看。如果是文本文件,那么在记事本上显示的就是文本,若是二进制文件,则出现的是一些乱码。

.java是文本文件,会根据字符集进行编码

图片是二进制文件:

五、文本权限

文件权限是操作系统中用于控制用户对文件或目录的访问级别的一种机制。通过设定权限可以从以下三种访问方式限制访问权限:

  1. 只允许用户自己访问;
  2. 允许一个预先指定的用户组中的用户访问;
  3. 允许系统中的任何用户访问

在Linux中,文本权限分为读、写、执行 三种,用r、w、x来表示。每个文件或目录都有三组权限,分别对应文件所有者、同组用户和其他用户。例如:"rwx r-x r--",表示文件所有者拥有的权限为可读可写可执行,同组用户的权限为可读可执行、其他用户只可读。

在Windows中,文本权限分为读取、写入、读取和执行、修改 ,分别用字母R、W、RX、M 表示。每个文件或文件夹都有一组权限,可以针对不同的用户或用户组进行设置。

六、Java中操作文件

在java中,是通过java.io.File类来对一个文件(包括目录)进行抽象描述的。

File中常见属性

表示系统相关的默认路径分隔符。

|-------------------|-------------------|-----------------------------|
| 修饰符及类型 | 属性 | 说明 |
| static String | pathSeparator | 依赖于系统的路径分隔符,String类型的表示 |
| static char | pathSeparator | 依赖于系统的路径分隔符,char类型的表示 |

File构造方法

|--------------------------------------|-----------------------------------------|
| 签名 | 说明 |
| File(String pathname) | 根据⽂件路径创建⼀个新的File实例,路径可以是绝对路径或者相对路径 |
| File(File parent,String child) | 根据⽗⽬录+孩⼦⽂件路径,创建⼀个新的File实例 |
| File(String parent,String child) | 根据⽗⽬录+孩⼦⽂件路径,创建⼀个新的File实 例,⽗⽬录⽤路径表示 |
| File(URI uri) | 通过将给定的文件 URI 转换为抽象路径名来创建新的 File 实例。 |

一般我们比较常用第一种构造方法,直接写出文件路径,如果我们写的是相对路径的时候,就需要明确基准路径是哪个。

代码中的相对路径的基准目录取决于运行程序的方式。

  • 直接在IDEA上运行,此时基准路径就是该项目所在的目录。例如下图,如果我们创建一个文件,此时的基准路径就是"D:\java-training\java1\FileText"。
  • 在命令行运行,通过java命令来运行,此时的基准路径就是java命令所处的目录
  • 某个程序,可能是被其他进程调用的,例如进程1通过创建子进程的方式,运行进程2,此时进程2的基准路径就和进程1的相同
  • 代码执行过程中,可以通过一些API修改基准路径,改成我们指定的某个路径。

File常用方法

|----------------|-------------------------|---------------------------------------------|
| 修饰符及返回值类型 | 方法签名 | 说明 |
| String | getParent() | 返回 File 对象的父目录文件路径 |
| String | getName() | 返回 FIle 对象的纯文件名称 |
| String | getPath() | 返回 File 对象的文件路径 |
| String | getAbsolutePath() | 返回 File 对象的绝对路径 |
| String | getCanonicalPath() | 返回 File 对象的修饰过的绝对路径 |
| boolean | exists() | 判断 File 对象描述的文件是否真实存在 |
| boolean | isDirectory() | 判断 File 对象代表的文件是否是一个目录 |
| boolean | isFile() | 判断 File 对象代表的文件是否是一个普通文件 |
| boolean | createNewFile() | 根据 File 对象,自动创建一个空文件。成功创建后返回 true |
| boolean | delete() | 根据 File 对象,删除该文件。成功删除后返回 true |
| void | deleteOnExit() | 根据 File 对象,标注文件将被删除,删除动作会到JVM 运行结束时才会进行 |
| String[] | list() | 返回 File 对象代表的目录下的所有文件名 |
| File[] | listFiles() | 返回 File 对象代表的目录下的所有文件,以 File 对象表示 |
| boolean | mkdir() | 创建 File 对象代表的目录 |
| boolean | mkdirs() | 创建 File 对象代表的目录,如果必要,会创建中间目录 |
| boolean | renameTo(File dest) | 进行文件改名,也可以视为我们平时的剪切、粘贴操作 |
| boolean | canRead() | 判断用户是否对文件有可读权限 |
| boolean | canWrite() | 判断用户是否对文件有可写权限 |

了解了File中相关的一些方法,那么我们就来使用这些方法看看。

在IDEA中,如果在构造File对象时,若使用"."那么默认的基准路径就是这个项目所在的位置。

七、相关方法使用案例

示例一:观察get方法的差异

. 表示当前目录,. .表示当前目录的上一级目录

java 复制代码
import java.io.File;
import java.io.IOException;

public class Demo {
   public static void main(String[] args) throws IOException {
        // 此处的路径指的是项目根目录
        // 创建一个File对象,参数是相对路径,此处并不需要文件实际存在
        File file= new File(".\\text.txt");
        // 输出文件的父目录路径
        System.out.println(file.getParent());
        // 输出文件名
        System.out.println(file.getName());
        // 输出文件的路径
        System.out.println(file.getPath());
        // 输出文件的绝对路径
        System.out.println(file.getAbsoluteFile());
        // 输出文件的规范化路径
        System.out.println(file.getCanonicalFile());
    }
}
java 复制代码
import java.io.File;
import java.io.IOException;

public class Demos1 {
    public static void main(String[] args) throws IOException {
        // 此处的路径指的是项目根目录
        // 创建一个File对象,参数是相对路径,此处并不需要文件实际存在
        File file= new File("..\\text.txt");
        // 输出文件的父目录路径
        System.out.println(file.getParent());
        // 输出文件名
        System.out.println(file.getName());
        // 输出文件的路径
        System.out.println(file.getPath());
        // 输出文件的绝对路径
        System.out.println(file.getAbsoluteFile());
        // 输出文件的规范化路径
        System.out.println(file.getCanonicalFile());
    }
}

getCanonicalPath()也是返回文件的绝对路径,但会去除[..]这样的符号,即返回的是标准的绝对路径.

示例二 :文件的创建

java 复制代码
import java.io.File;
import java.io.IOException;

public class Demo {
    public static void main(String[] args) throws IOException {
        // 创建一个File对象,指向一个不存在的文件路径,以便后续观察文件的创建
        File file=new File(".\\text.txt");
        // 输出文件是否存在
        System.out.println(file.exists());
        // 输出文件是否为目录
        System.out.println(file.isDirectory());
        // 输出文件是否为文件
        System.out.println(file.isFile());
        // 尝试创建新文件,并输出结果
        System.out.println(file.createNewFile());
        // 再次输出文件是否存在
        System.out.println(file.exists());
        // 再次输出文件是否为目录
        System.out.println(file.isDirectory());
        // 再次输出文件是否为文件
        System.out.println(file.isFile());
        // 再次尝试创建新文件,并输出结果
        System.out.println(file.createNewFile());
    }

}

我们可以看到,当我们没有运行程序之前,是没有text文本的,当我们运行之后,在项目中会出现一个text文本文件。

当我们调用createNewFile()方法的时候,其实是会报红的,要求我们抛出IO异常。

为什么需要抛出IO异常呢?

文件的创建是不一定成功的,

1.文件系统错误:

  • 如果指定的文件已经存在,则无法创建新的文件。
  • 如果文件系统的磁盘空间不足,无法创建新文件。
  • 如果文件路径无效或不可达,例如路径中的目录不存在。

2.权限问题:

  • 如果当前用户没有足够的权限来创建文件
  • 如果目标目录不可写。

3.安全限制:

  • 在某些安全策略下,应用程序可能被禁止创建文件。

示例三:文件的删除

delete:如果文件不存在,那么就会返回false,反之,如果文件删除成功,就会返回true。

只要调用到delete方法,就会立即删除文件。

java 复制代码
import java.io.File;
import java.io.IOException;

public class Demos3 {
    /**
     * 主函数,用于演示File类的使用
     * @param args 命令行参数
     * @throws IOException 当文件操作引发IO异常时抛出
     * @throws InterruptedException 当线程休眠被中断时抛出
     */
    public static void main(String[] args) throws IOException, InterruptedException {
        // 创建一个指向当前目录下text.txt文件的File对象
        File file=new File(".\\text.txt");
        // 检查文件是否存在并打印结果
        System.out.println("文件是否存在"+file.exists());
        // 尝试创建文件,打印创建结果(true表示成功,false表示失败)
        System.out.println("创建文件是否成功:"+file.createNewFile());
        System.out.println("文件是否存在"+file.exists());
        // 让线程休眠10秒,方便查看文件创建结果
        Thread.sleep(10000);
        // 尝试删除文件,打印删除结果(true表示成功,false表示失败)
        System.out.println("文件是否删除成功:"+file.delete());
        System.out.println("文件是否存在"+file.exists());
    }

}

在运行的过程中,我们可以打开项目所在路径查看运行先后text文本是否存在。


deleteOnExit:根据 File 对象,标注文件将被删除,删除动作会到JVM 运行结束时才会进行

java 复制代码
import java.io.File;
import java.io.IOException;

public class Demos4 {
    public static void main(String[] args) throws IOException, InterruptedException {
        // 创建一个指向当前目录下text.txt文件的File对象
        File file=new File(".\\text.txt");
        // 检查文件是否存在并打印结果
        System.out.println("文件是否存在"+file.exists());
        // 尝试创建文件,打印创建结果(true表示成功,false表示失败)
        System.out.println("创建文件是否成功:"+file.createNewFile());
        System.out.println("文件是否存在"+file.exists());
        // 让线程休眠5秒,方便查看文件创建结果
        Thread.sleep(5000);
        // 删除文件,并设置删除操作在JVM退出时执行
        file.deleteOnExit();
        System.out.println("文件是否存在"+file.exists());
    }
}

可以看到,当程序还没停止的时候,文件是还没被删除的。

示例四:打印目标目录内的所有文件

java 复制代码
import java.io.File;
import java.util.Arrays;

public class Demo5 {
    /**
     * 程序的入口点
     * 该方法主要用于列出当前目录下所有文件的名称
     * @param args 命令行参数,本程序中未使用
     */
    public static void main(String[] args) {
        // 创建File对象,用于操作文件和目录
        File file=new File(".\\src\\FileT");// 获取当前目录
        // 列出当前目录下的所有文件名
        String[] lists=file.list();
        // 打印文件名数组
        System.out.println(Arrays.toString(lists));
    }
}

示例五:打印项目内所有的文件路径

可以使用递归的方式,如果是文件就直接打印,若是目录,则再次调用方法。

java 复制代码
import java.io.File;
import java.io.IOException;

public class Demos5 {
    /**
     * 递归扫描给定文件数组中的所有文件和子文件夹,并打印出所有文件的规范路径。
     * 
     * @param files 文件数组,包含要扫描的文件和文件夹。
     * @throws IOException 当无法读取文件属性或目录内容时抛出。
     */
    public static void scan(File[] files) throws IOException {
        // 遍历文件数组中的每个元素
        for(File f:files){
            // 如果当前元素是一个目录,则递归扫描该目录下的所有文件和子目录
            if(f.isDirectory()){
                scan(f.listFiles());
            }else{
                // 如果当前元素是一个文件,则打印出该文件的规范路径
                System.out.println(f.getCanonicalFile());
            }
        }
    }

    public static void main(String[] args) throws IOException {
        File file=new File(".");//当前目录
        scan(file.listFiles());
    }
}

示例六:创建目录

mkdir()只能创建一级目录,想要创建多级目录需要使用mkdirs()

java 复制代码
import java.io.File;

public class Demos6 {
    /**
     * 程序的主入口点
     * 此方法用于演示如何在Java中创建一个新文件夹
     * @param args 命令行参数,本例中未使用
     */
    public static void main(String[] args) {
        // 创建一个指向新文件夹的File对象
        File file = new File(".\\newLib");
        // 创建文件夹
        System.out.println("文件夹是否创建成功:"+file.mkdir());
    }

}

利用**mkdirs()**可以创建多级目录

java 复制代码
package FileT;

import java.io.File;

/**
 * Demos6 类用于演示文件操作
 */
public class Demos6 {
    
    /**
     * 程序的主入口点
     * 此方法用于演示如何在Java中创建多层文件夹
     * @param args 命令行参数,本例中未使用
     */
    public static void main(String[] args) {
        // 创建一个指向新文件夹的File对象
        File file = new File(".\\newLib\\abc\\def");
        // 创建文件夹
        System.out.println("多层文件夹是否创建成功:"+file.mkdirs());
    }
}

示例七:文件/文件夹的改名(剪切)

我们利用上面例子创建的多层目录,修改第一层目录的名,将newLib改为Lib。

java 复制代码
import java.io.File;

public class Demos7 {
    public static void main(String[] args) {
        // 创建文件对象,构造方法中传入路径
        File file=new File(".\\newLib");
        // 创建另一个文件对象,用于后续的重命名操作
        File files=new File(".\\Lib");
        // 重命名文件,将"newLib"目录重命名为"Lib"
        file.renameTo(files);
    }
}

当然,其实这里也可以用作剪切,将Lib目录下的abc目录以及其下的def目录移植到与Lib同级。

java 复制代码
import java.io.File;

public class Demos7 {
    /**
     * 程序的入口点
     * 将一个目录重命名为新的名称
     */
    public static void main(String[] args) {
        // 创建一个指向当前目录下名为"Lib/abc"的File对象
        File file=new File(".\\Lib\\abc");
        // 创建一个指向当前目录下名为"abc"的File对象
        File files=new File(".\\abc");
        // 将"Lib/abc"目录重命名为"abc"
        file.renameTo(files);
    }

}

当然,也可以对文件进行重命名。

java 复制代码
import java.io.File;
import java.io.IOException;

public class Demos8 {
    /**
     * 主函数,用于演示如何创建并重命名文件
     * @param args 命令行参数
     * @throws IOException 如果创建文件时发生IO异常
     * @throws InterruptedException 如果线程等待时被中断
     */
    public static void main(String[] args) throws IOException, InterruptedException {
        // 创建一个指向当前目录下名为"text.txt"的文件对象
        File file=new File(".\\text.txt");
        // 如果文件不存在,则创建一个新文件
        System.out.println("文件是否创建成功:"+file.createNewFile());
        System.out.println(file.getName());
        // 延迟5秒,以便观察文件修改前的状态
        Thread.sleep(5000);
        // 创建一个指向当前目录下名为"text1.txt"的文件对象
        File files=new File(".\\text1.txt");
        // 将原文件重命名为新文件名
        System.out.println("重名是否成功:"+file.renameTo(files));
    }
}

示例八:查看文件的权限

我们可以使用**canRead()和canWrite()**来查看文件是否可读可写。

java 复制代码
import java.io.File;
import java.io.IOException;

public class Demos9 {
    public static void main(String[] args) throws IOException {
        File file=new File(".\\text.txt");
        System.out.println("文件是否创建成功:"+file.createNewFile());
        System.out.println("文件是否可读:"+file.canRead());
        System.out.println("文件是否可写:"+file.canWrite());
    }
}

以上就是本篇关于文件操作所有内容,若有不足,欢迎指正~

相关推荐
Elastic 中国社区官方博客1 分钟前
Elasticsearch 和 Kibana 8.16:Kibana 获得上下文和 BBQ 速度并节省开支!
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
StudyHappiness1 分钟前
MongoDB新版本,单节点安装
linux·运维·mongodb·kylin
晴天のVlog4 分钟前
Fastapi使用MongoDB作为数据库
数据库·python·mongodb·fastapi
微服务商城技术分享10 分钟前
通过Docker实现openGauss的快速容器化安装
运维·docker·容器
卓越小Y10 分钟前
配置jellyfin docker 硬件加速
java·spring cloud·docker
白萝卜弟弟13 分钟前
【JAVA】正则表达式中的捕获组和非捕获组
java·正则表达式
Desmend__17 分钟前
正则表达式那些事儿
数据库·mysql·正则表达式
袁庭新34 分钟前
LuaRocks如何安装数据库驱动?
java·数据库·redis·lua·luarocks·袁庭新
hummhumm42 分钟前
第 10 章 - Go语言字符串操作
java·后端·python·sql·算法·golang·database
Narutolxy1 小时前
从 MySQL 5.7 到 8.0:理解 GROUP BY 的新规则与实战优化20241112
数据库