IO——File及File 类

基础知识

硬件:处理器( C pU )、存储器(内存)、 l/O:输入设备( Input Device )和 输出设备( Output Device )

CPU 只能和内存做直接的数据交换

lnput Device :现实中的物理信号(光信号 e.g.摄像头、电信号、波信号 e.g.声音)一>数字格式.存储在内存中

Output Device :数字一>物理信号

IO设备:显示器( O )、触屏显示器( IO )、鼠标( l )、键盘( l )、摄像头( I )、麦克风( l ) 、器声扬( O ) 、 硬盘( IO )、网卡( IO )

image-20220709015458322

变量、对象本质上是编程语言对硬件中内存的抽象

内存(Memory)又被称为RAM(Random Access Memory),支持以O(1)时间复杂度根据下标(内存地址)访问的存储

各个存储访问速度的直观感受

image-20220707200343726

硬盘(Hard Disk Drive, HDD)的实现

  1. 磁盘:利用磁性实现的一种方式, 硬盘(机械硬盘)一般都是指磁盘

  2. 固态硬盘(Solid State Disk, SSD)

  3. 闪存 (Flash Memoty)

磁盘更适合做连续数据的读写,而不是和做随机数据的读写。磁盘寻址步骤:

  1. 旋转转片找到对应扇区
  2. 找到对应磁道
image-20220707201012899

软件层面认识硬盘中的数据:

image-20220707201246658

文件是对硬盘中数据的抽象概念

认识文件

狭义上的文件(file):针对硬盘这种持久化存储的I/O设备,当我们想要进行数据保存时,往往不是保存成一个整体,而是独立成一个个的单位进行保存,这个独立的单位就被抽象成文件的概念,就类似办公桌上的一份份真实的文件一般。即,文件是对硬盘中数据的抽象概念(因此硬盘数据的读写 ==> 文件的读写问题

  • 文件由OS +文件系统( Filesystem )统一管理

  • 文件的读写问题:文件由于被操作系统进行了管理,所以根据不同的用户,会赋予用户不同的对待该文件的权限,一般地可以认为有可读、可写、可执行权限。)

  • 文件数据 = 内容数据 + 元信息

    • 文件的元信息:指文件名、文件类型、文件大小等,并不作为文件的数据而存在的信息。

很多操作系统为了实现接口的统一性,将所有的 I/O 设备都抽象成了文件的概念,使用这一理念最为知名的就是 Unix、Linux 操作系统 —— 万物皆文件。

Windows 操作系统上,还有一类文件比较特殊,就是平时我们看到的快捷方式(shortcut),这种文件只是对真实文件的一种引用而已。其他操作系统上也有类似的概念,例如,软链接(soft link)等。

树型结构组织 和 目录

我们看到的文件的基本知识

1.文件被以树形结构(数据结构学过的树,但不是二叉树)进行管理,文件都是树上的结点(node)

2.文件可以大体分成两大类

1)普通文件:就是俗称的文件,是用于存储数据的文件

  • 普通文件又可分为:

    • 文本文件(被字符集编码的文本,如:.txt)

    • 不是文本的文件(按照标准格式保存的非被字符集编码过的文件,二进制文件,如:.class、.gpn)

  • 文件后缀( file suffiex ):也称文件扩展名,在 Windows OS 下,以文件后缀来标记出这个文件文存储的内容是什么内容,如:*. txt 普通文本 、 * . docx Word 文档。文件扩展名可以被显示或隐藏

2)目录/文件夹( directory,dir/folder ) :用于管理树形结构组织数据的文件

  • 以 / 结尾,代表这个结点是目录(当Windows 是个目录时,C : /Windows 等价于 C :/Windows / )

  • 无论是目录或文件都只是树上的一个节点,一个节点可以有多个孩子

3.文件树只是一个逻辑结构,而不是硬盘上的物理结构

image-20220707213445801

作为软件开发工程师大部分场景只需要关注这个逻辑结构即可,不需要管理物理结构

image-20220707213518426

文件路径(Path)

关于文件的路径( path ) : 根据一个规则,从文件树上唯一确定一个位置一定对应到某个结点,但是这个结点可以不存在

路径分类

  1. 绝对路径( a bsolute path abs path ) :从一棵树的根结点出发描述的路径 。(无论‘我们‘身在何处,总是唯一确定一个位置)

  2. 相对路径( relative path ) :从‘我们’所在的当前位置出发,描述的路径。(“我们“的位置一变,路径就可能失效了)

我们所在的位置一定是一个目录,我们是不能处于一个文件上的。

首先找到我的父结点( Windows ) ,再去到父亲结点( C :)、找到它的叫做 a . txt 的孩子

最基本的相对路径:

什么叫做“我们”所在的位置:每个进程都有一个当前工作目录( current working directory,cwd ) ,一般一个进程的启动目录,就是当前工作目录

image-20220707213548804

进程区行时的工作目录在哪里? current working diretory cwd

image-20220708215113097

JVM下,通常就是进程启动时的目录! ! 但这个目录可以改变[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y7JqDRne-1657515798775)(img/image-20220708215849154.png)]

注意,原则上是启动时的目录,而和代码/工程所在目录无关。

image-20220707223401499

因此,使用文件的相对路径时,要在前边加上 … 用以返回文件真正的父节点

真实中怎么去描述路径 (重点)

windows 下,先以绝对路径为例:

D :\ 课程 \ 2022 - 06 - 27 - 2022 火箭班 \ 板书.png

  • \ : 俗称路径分隔符( path separator )

  • C:、 D :、 E :代表的就是根。所以,这个以根开头的路径一定是个绝对路径 , 由 ‘文件名+文件名+文件名 … 组成

  • 步骤:

    • 从根 D : 开始
    • 找到 “ D : ” 的孩子“课程”
    • 找到 “课程” 的孩子 2022 …
    • 找到 ”2022 … “ 的孩子 板书.png

当我们身处 “ D:\课程 ” 时,下面这个相对路径和上面的绝对路径描述的是同一个结点:

2022 - 06 - 27 - 2022 火箭班 \ 板书.png (不是由根开始,所以是相对路径)

路径的表示

Windows 使用\作为路径分隔符, Linux( Unix / XOS )使用/作为路径分隔符。好在我们写的是 Java , Java 号称跨平台,所以帮我们处理这个问题我们代码中写” / ”或者” \ \ ”都可以。由于” / ”不用转义,所以我一般使用” / ”为主。

例,在代码的字符串中如何表示这个路径:

String path = " D : \课程\2022 - 06 - 27 - 2022 火箭班 - IO "

在java中直接这么写的错误的,因为字符串中反斜杠( \ ) ,表示转义的意思,比如:\ n 、\ t …

应该写作 :

  • String path =” D : \\ 课程 \\ 2022 - 06 - 27 - 2022 火箭班 - IO ”,使用 \\ 转义后表示\ 。
  • String path = " D : / 课程 / 2022 - 06 - 27 - 2022 火箭班 - IO ” 同样是正确的

路径表示中的两个特殊的符号一个点( " . " )和两个点(”…” ) 。其中:

  • " . ”表示在当前位置(目录)不同
  • ”…”表示回到当前位置的父结点(目录)上

举例说明:

  • C : /Windows / Users / hello . jpg

  • C : /Windows/./users / hello.jpg :这里的“.”表示还是在当前位置没动

  • C : / Windows /…/Windows / Users / hello.jpg: 这里的“…”表示回到父目录 C盘

  • C : /…/…/…/…/Windows / Users / hello.jpg: 根再回到双亲也还是根

  • C : / . / . / . / . / Windows / Users / hello.jpg

这两个符号一般在相对路径上使用较多,例如,我现在在 C : / Windows / Users 下:

  • …/…/ a . txt : 表示 C : / a . txt

  • . / hello.jpg :表示 C : / Windows / Users / hello.jpg

  • hello.jpg :表示 C : /Windows / Users / hello.jpg

关于文件的路径总结

1 .路径是树上找到一个结点的位置

2 .路径并不表示文件一定存在

3 .路径分为绝对路径 or 相对路径

4 .当前位置二进程的当前工作目录

5 .文件路径” / ”或者” \ \ ”表示路径分隔符, Java 下使用哪个都可以

6 . " . ”和 “…” 的含义

文件的结构

树的结点分为:叶子节点 和 非叶子节点

  • 普通文件:叶子节点

  • 目录文件:叶子节点(空目录) 和 非叶子节点

对树结构来说,对结点的操作更容易、子树的操作更复杂,因此文件系统中,以结点为单元进行操作(在代码层面)

  • 文件移动操作(文件重命名、文件剪切+粘贴):结点的移动(重命名 or 移动到其他结点下)

  • 文件复制操作(复制+粘贴):新建结点+内容的复制

  • 目录移动操作(目录重命名、目录剪切+粘贴):以该结点为根的一棵子树的移动

  • 目录复制操作:以该结点为根的一裸子树的复制

  • 删除:默认情况下只能删除普通文件 or 空目录。只能删除结点,不能删除子树

  • 删除非空目录:对整棵树的删除

而对树的操作,则需要转换成对结点的操作,以目录的复制为例,深度 or 广度遍历整棵树,然后对其中的每个结点进行复制.

通过 Java 代码操作文件( FiIe )

文件数据=元数据(属性数据)+内容数据

接下来,我们只关注涉及元数据的操作,暂时不涉及内容数据的读写。如:

  • 对文件系统树的操作:判断是否存在、判断是否是目录、创建、删除、重命名 …

File概述

FiIe 对象描述一个文件(这是一个结点,但结点对应的文件是否存在并不一定)

代码要求:

  • SE+ DS:要求我们学过的所有代码,闭卷考试的要求:可以脱离IDEA环境熟练地编写和使用,熟悉常见类的常见方法因为最终是为 OJ 服务的。(OJ一般不允许在IDEA上编写)

  • DB 之后的所有代码,是开卷考试的要求:对常见类有个印象,可以结合IDEA工具,查网络资料编写出来即可

  • 所有类必须放在某个包( package )下,习惯上包的命名习惯: com . io . Demo1…

构造方法

image-20220708105522506

方法

创建一个新文件

image-20220708105641340

  • 返回true:创建成功
  • 返回false:创建失败(文件已经存在)
  • 抛出IOException:发生了IO异常(最常见的的是文件所在的目录现在还不存在)
// 1. 绝对路径方式创建文件对象
// (仅创建了对象,并未真正在电脑上创建文件,还需要调用createNewFile方法)
// 1.1 直接传入字符串路径
File file1 = new File("E:\\JavaStudy\\Bite比特\\课件\\课堂程序\\hello.txt");
// 1.2 传入父路径+子路径
File file2 = new File("E:\\JavaStudy\\Bite比特\\课件\\课堂程序","hello.txt");
// 1.3 以File对象形式传入parent
File parent = new File("E:\\JavaStudy\\Bite比特\\课件\\课堂程序");
File file3 = new File(parent,"hello.txt");

// 2. 常用方法
// 2.1 compareTo: 比较文件路径,负数:file1<file2  正数:file1>file2  0:file1==file2
int comp1 = file1.compareTo(file2);
int comp2 = file2.compareTo(file3);
System.out.println(comp1);
System.out.println(comp2);
// 2.2 creatNewFile创建文件
File file4 = new File("E:\\JavaStudy\\Bite比特\\课件\\课堂程序\\IO2\\hello.txt");
file4.createNewFile(); // 文件目录IO2不存在,抛出java.io.IOException异常
// 异常的知识点:Java 中的异常分为 受查异常(checked exception) or 非受查异常(uncheck exception)
// 方法中如果抛出受查异常,有语法要求
// 要么,我们自己 try catch,不再抛出受查异常
// 要么,在方法签名中通过 throws 声明有受查异常可能被抛出
// 故 java.io.IOException 是受查异常
//    java.lang.RuntimeException 及其子类是非受查异常

File file5 = new File("E:\\JavaStudy\\Bite比特\\课件\\课堂程序\\IO\\hello.txt");
boolean r1 = file5.createNewFile();
System.out.println(r1); // 文件尚未被创建,所以是 true

r1 = file5.createNewFile();
System.out.println(r1); // 文件被创建过了,所以是 false
删除一个文件

image-20220708105718659

delete ( ) vs deleteOnExit ( )

delete():立即删除,只能操作叶子节点(普通文件或空目录)

  • 返回true:删除成功
  • 返回false:对应文件不存在导致的删除失败,对非空目录进行操作导致的失败
  • 抛出IOException:其他情况失败(如:文件被其他进程正在使用打开)
  • delete ( )是不进入回收站的删除,是真正的删除 ;windows 上的回收站的删除,实际上只是把文件剪切到一个固定目录

deleteOnExit():在 JVM 退出时才真正删除,可以操作普通文件或空目录

删除非空目录
  1. 先遍历(深度优先 ― 递归),删除这个目录下的所有子孙,让这个目录变成空目录

  2. 删除该目录

    import java.io.File;
    import java.io.IOException;
    
    public class Demo2 {
    
        public static void main(String[] args) throws IOException {
            // 1. 删除普通文件
            File file = new File("E:\\JavaStudy\\Bite比特\\课件\\课堂程序\\IO\\hello.txt");
            file.delete();
            
            // 2. 删除非空目录
            File file1 = new File("E:\\JavaStudy\\Bite比特\\课件\\课堂程序\\IO");
            // 1) 删除非空目录file1下的所有子孙文件
            traversal(file1);
            // 2) 删除该目录
            file1.delete();
        }
    
        /**
         * 利用广度优先的方式删除一个非空目录
         * @param dir
         * @throws IOException
         */
        private static void traversal(File dir) throws IOException {
            File[] files = dir.listFiles(); // 查看这个目录下的所有孩子(不是子孙)
            for (File file : files) {
                // 若这个孩子也是目录,继续深度优先进行遍历,删除这个孩子的子孙文件
                if(file.isDirectory()){
                    System.out.println("目录:"+file.getCanonicalPath()+"\\");
                    // 删除这个目录下的文件,使该目录变为空目录,可以使用delete方法
                    traversal(file);
                    file.delete();
                }else {
                    // 这个孩子是普通文件,直接删除
                    // 得到文件的一个标准的路径(去除一切无意义的 . 和 ..)
                    System.out.println("文件:"+file.getCanonicalPath());
                    file.delete();
                }
            }
        }
    }
    

delete方法删除情况:

  1. 普通文件删除(存在): true

  2. 普通文件删除(不存在):false

  3. 空目录删除(存在):true

  4. 非空目录删除:false(必须递归解决)

其他常用方法

image-20220708195803366

  • isDirectory ( ): 文件存在&&文件是文件夹

    isFile ( ) 文件存在&&文件是普通文件

  • 例:

    File file = new File("..\\hello-world.txt"); 
    

    getName ( ) :得到文件名 —> hello-world.txt

    getParent ( ) :得到父目录 —> …

    isAbsolute():判断对象是根据相对路径还是绝对路径(有根节点)创建,false相对,true绝对 —> false

    getPath():得到传入对象的路径(相对或绝对)—> …\hello-world.txt

    getAbsolutePath():absolute path 一般的绝对路径 —> D:\代码练习\文件示例1\…\hello-world.txt

    getCanonicalPath():canonical path 标准的绝对路径(去掉了无意义的 . 和 …) —> D:\代码练习\hello-world.txt

注意:使用文件的相对路径时,要在前边加上 … 用以返回文件真正的父节点。例:

// IDEA 配置的默认启动位置就是工程目录下
File file5 = new File("hello.txt"); 
System.out.println(file5.getCanonicalPath()); // 得到的是工程目录+文件名,不是文件的真正路径
File file6 = new File("..\\hello.txt");
System.out.println(file6.getCanonicalPath()); // 先返回了根目录,得到的是文件的真正路径

使用绝对路径就没有这个问题

File file1 = new File("E:\\JavaStudy\\Bite比特\\课件\\课堂程序\\IO\\hello.txt");
System.out.println(file1.exists());
System.out.println(file1.isDirectory());
System.out.println(file1.isFile());

File file2 = new File("E:\\..\\.\\..\\JavaStudy\\Bite比特\\课件\\课堂程序\\IO\\");
String absolutePath = file1.getAbsolutePath();
String canonicalPath = file1.getCanonicalPath();
System.out.println(absolutePath);
System.out.println(canonicalPath);
System.out.println(file2.getName());
System.out.println(file2.getParent()); System.out.println(file2.getParentFile().getCanonicalPath());

IastModified ( ): 得到该文件最后一次被修改的时间(以时间戳 timestamp 形式表现)

System.currentTimeMillis():得到当前时间的时间戳timestamp,代表从某个时刻(固定值)到某个时间经过的秒数\毫秒数

long s = System.currentTimeMillis();    // 当前时间的时间戳,单位:毫秒
Thread.sleep(1000);
long e = System.currentTimeMillis();
long passMs = e - s; // 经过的毫秒数
System.out.println(passMs); 

File[] listFiles():返回目录下的所有孩子,常用于做树的遍历(多个孩子的树:深度优先遍历——数组,广度优先遍历——队列)

File[] files1 = file1.listFiles(); // 叶子节点对象,返回null
File[] files2 = file2.listFiles(); // 空目录对象,返回空数组: []
System.out.println(Arrays.toString(files1));
System.out.println(Arrays.toString(files2));

image-20220708210506635

createNewFile、mkdir、mkdirs方法的区别

createNewFile ( ) :创建是个普通文件

mkdir ( ) :make directory创建是个目录文件,失败原因:文件已经存在、路径上的祖先不存在

mkdirs():创建是个目录文件,可以一并把路径中目前不存在的目录都创建出来。

// a b c 是未创建的目录,若是创建\\c\\hello.txt,则将hello.txt作为目录名创建一个新文件
File file3 = new File("E:\\JavaStudy\\Bite比特\\课件\\课堂程序\\IO\\a\\b\\c");
System.out.println(file3.mkdirs());

boolean renameTo ( File dest ):重命名,可实现 1.文件修改名称 2.剪切+粘贴

File file4 = new File("E:\\JavaStudy\\Bite比特\\课件\\课堂程序\\IO\\hello.txt");
// 1.文件修改名称
File dest1 = new File("E:\\JavaStudy\\Bite比特\\课件\\课堂程序\\IO\\bye.txt");
file4.renameTo(dest1);
// 2.剪切+粘贴
File dest2 = new File("E:\\JavaStudy\\Bite比特\\课件\\课堂程序\\IO\\a\\hello.txt");
dest1.renameTo(dest2);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MultipartFile是spring框架中的一个型,用于表示通过HTML中的form data方式上传的文件。它包含了二进制数据和文件名称。而FileJava中的一个,用于表示文件在文件系统中的存在。 区别在于MultipartFile是用于在web应用中处理文件上传的对象,它提供了一些方法来获取文件的相关信息,如文件名、文件型、文件大小等。而File是用于在Java程序中对文件进行操作的对象,它可以用来创建、删除、重命名、移动文件等。另外,MultipartFile可以将文件转换为File对象进行操作,也可以从File对象中创建MultipartFile对象。可以通过调用MultipartFile对象的length()方法来获取文件的长度。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [带你领略IO的魅力——File与MultipartFile的相互转换](https://blog.csdn.net/weixin_42083036/article/details/105687214)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Java_File和MultipartFile](https://blog.csdn.net/weixin_40877388/article/details/114984621)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值