JavaWeb20-文件操作和IO

本文详细介绍了文件的基本概念,包括文件结构、路径(绝对路径与相对路径)、文件类型和权限。在Java中,通过`java.io.File`类来操作文件,包括获取文件元信息、路径处理、文件的创建、删除和重命名。此外,还讲解了文件内容的读写,涉及InputStream和OutputStream,以及使用Scanner和PrintWriter进行数据交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.认识文件

1.1.文件结构组织和目录

1.2.文件路径(Path)

1.2.1.绝对路径

1.2.2.相对路径

1.3.文件类型

1.3.1.文本文件(.txt结尾)

1.3.2.二进制文件

1.4.文件权限

1.5.其他

2.Java中操作文件

2.1.File常见属性

2.2.File常用构造方法

2.3.File常用方法

2.3.1.观察get系列的特点和差异

--->PS:getPath() VS getAbsolutePath() VS getCanonicalPath()

2.3.2.文件判断与创建

2.3.3.文件存在删除/不存在创建

2.3.4.观察deleteOnExit

--->PS:delete() & deleteOnExit() 区别

2.3.5.观察目录的创建

2.3.6.观察文件重命名

3.文件内容的读写——数据流

3.1.InputStream:输入流

3.1.1.InputStream常用方法

3.1.2.FileInputStream

3.1.3.使用Scanner进行数据读取

3.2.OutputStream:输出流

3.2.1.OutputStream 常用方法

3.2.3.使用 PrintWriter 进行写入

3.2.4.使用FileWriter追加数据


1.认识文件

先来认识狭义上的⽂件(file)。针对硬盘这种持久化存储的I/O设备,当想要进⾏数据保存时,往往不是保存成⼀个整体,⽽是独⽴成⼀个个的单位进⾏保存,这个独⽴的单位就被抽象成⽂件的概念, 就类似办公桌上的⼀份份真实的⽂件⼀般。

⽂件除了有数据内容之外,还有⼀部分信息,例如⽂件名、⽂件类型、⽂件⼤⼩等并不作为⽂件的数据⽽存在,我们把这部分信息可以视为⽂件的元信息。

1.1.文件结构组织和目录

如何进⾏⽂件的组织:按照层级结构进⾏组织 —— 数据结构中学习过的树形结构。这样,⼀种专⻔⽤来存放管理信息的特殊⽂件诞⽣了,也就是我们平时所谓⽂件夹(folder)或者⽬录(directory)的概念。

PS:⽂件夹是⽤来存放⽂件的,⽐如 A ⽂件夹下有 N 个⽂件,⽽ A ⽂件夹有⾃⼰的⽬录,⽐如在D:\\A。

1.2.文件路径(Path)

1.2.1.绝对路径

在⽂件系统中如何定位⼀个唯⼀的⽂件?从树型结构的⻆度来看,树中的每个结点都可以被⼀条从根开始,⼀直到达的结点的路径所描述,⽽这种描述⽅式就被称为⽂件的绝对路径(absolute path)。

Linux必须以"-"开始的全路径;Windows可以省略"此电脑",直接从某个盘符开始。

1.2.2.相对路径

可以从任意结点出发,进⾏路径的描述,⽽这种描述⽅式就被称为相对路径(relative path),相对于当前所在结点的⼀条路径。

Linux中以".-"表示当前路径。

1.3.文件类型

即使是普通⽂件,根据其保存数据的不同,也经常被分为不同的类型,⼀般简单划分为:

1.3.1.文本文件(.txt结尾)

指代保存被字符集编码的⽂本。

1.3.2.二进制文件

按照标准格式保存的非被字符集编码过的⽂件。

Windows 操作系统上,会按照文件名中的后缀来确定文件类型以及该类型文件的默认打开程序。但这个习俗并不是通用的,在 OSXUnixLinux 等操作系统上,就没有这样的习惯,一般不对文件类型做如此精确地分类。

1.4.文件权限

⽂件由于被操作系统进⾏了管理,所以根据不同的⽤户,会赋予⽤户不同的对待该⽂件的权限,⼀般地可以认为有可读可写可执行权限。

文件权限设置语法:

  • Linux:chmod + rwx 文件夹/文件。
  • Windows:文件右击->属性->安全->编辑->针对不同用户进行权限的赋值。

1.5.其他

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

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

2.Java中操作文件

此篇文章主要涉及⽂件的元信息、路径的操作,暂时不涉及关于⽂件中内容的读写操作。

Java 中通过 java.io.File 类来对⼀个⽂件(包括⽬录)进⾏抽象的描述。注意,有 File 对象,并不代表真实存在该⽂件。

2.1.File常见属性

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

2.2.File常用构造方法

签名
说明
File(File parent, String child)
根据⽗⽬录 + 孩⼦⽂件路径,创建⼀个新的 File实例
File(String pathname)
根据文件路径创建一个新的 File 实例,路径可以是绝对路径或者相对路径
File(String parent, String child)
根据父目录 + 孩子文件路径,创建一个新的 File 实例,父目录用路径表示
import java.io.File;

public class FileDemo1 {
    public static void main(String[] args) {
        File pFile = new File("d:\\");

        //构造方法1
        File file = new File(pFile, "a.txt");
        System.out.println(file.getPath());

        //构造方法2【重点-常用】
        File file2 = new File("d:\\b.txt");
        System.out.println("文件2路径:" + file2.getPath());

        //构造方法3
        File file3 = new File("d:\\", "c.txt");
        System.out.println(file3.getPath());
    }
}

2.3.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()
判断用户是否对文件有可写权限

2.3.1.观察get系列的特点和差异

import java.io.File;
import java.io.IOException;

public class FileDemo2 {
    public static void main(String[] args) throws IOException {
        File file = new File("../a.txt");
        System.out.println("文件名称:" + file.getName());
        System.out.println("文件目录(getPath):" + file.getPath());
        System.out.println("文件绝对路径:" + file.getAbsolutePath());
        System.out.println("文件标准路径:" + file.getCanonicalPath());
    }
}

--->PS:getPath() VS getAbsolutePath() VS getCanonicalPath()

  1. 绝对路径时,三者⼀致。
  2. 相对路径时:
  • getPath() 是相对路径本身。
  • getAbsolutePath() 是项⽬⽬录 + 相对路径本身(不是一个路径)。
  • getCanonicalPath() 可以解析相对路径,得到真正意义上不出错的路径。

2.3.2.文件判断与创建

注:文件名不能包含下列任何字符:\、/、:、*、?、"、<、>、|。

import java.io.File;
import java.io.IOException;

public class FileDemo3 {
    public static void main(String[] args) throws IOException {
        File file = new File("z.txt");
        System.out.println("文件是否存在:" + file.exists());
        System.out.println("是否为文件夹:" + file.isDirectory());
        System.out.println("是否为文件:" + file.isFile());
        System.out.println();

        boolean result = file.createNewFile(); //创建文件
        System.out.println("文件创建:" + result);
        System.out.println("文件是否存在:" + file.exists());
        System.out.println("是否为文件夹:" + file.isDirectory());
        System.out.println("是否为文件:" + file.isFile());
        System.out.println();

        File file2 = new File("c.txt");
        if(!file2.exists()) { //文件不存在,创建文件
            System.out.println("创建文件:" + file2.createNewFile());
        }
        System.out.println("是否为文件夹:" + file2.isDirectory());
        System.out.println("是否为文件:" + file2.isFile());
    }
}

如果⽂件和⽂件夹不存在,使⽤ isDirectory 和 isFile 判断都为 false。

2.3.3.文件存在删除/不存在创建

import java.io.File;
import java.io.IOException;

public class FileDemo4 {
    public static void main(String[] args) throws IOException {
        //先得到一个file对象
        File file = new File("a.txt");
        //判断file对象是否存在
        if(file.exists()) {
            //如果存在则删除文件
            boolean result = file.delete();
            System.out.println("文件删除:" + result);
        } else {
            //如果不存在则创建文件
            boolean result = file.createNewFile();
            System.out.println("新建文件:" + result);
        }
    }
}

2.3.4.观察deleteOnExit

import java.io.File;
import java.io.IOException;

public class FileDemo5 {
    public static void main(String[] args) throws IOException, InterruptedException {
        File file = new File("a.txt");
        if(!file.exists()) {
            //如果不存在,则新建
            System.out.println("新建文件:" + file.createNewFile());
        }
        //删除文件
        file.deleteOnExit();
        Thread.sleep(5 * 1000);
    }
}

--->PS:delete() & deleteOnExit() 区别

  1. delete() 有返回值;deleteOnExit() 无返回值。
  2. delete() 若在开始执行后手动关闭程序,文件会被删除;deleteOnExit() 若在开始执行后手动关闭程序,文件不会被删除。
  3. 二者在程序自然运行结束后都会删除文件,是一样的。

2.3.5.观察目录的创建

import java.io.File;

public class FileDemo6 {
    public static void main(String[] args) {
        File file = new File("test/apps");
        System.out.println("是否为文件夹:" + file.isDirectory());
        System.out.println("是否为文件:" + file.isFile());
        System.out.println();

//        boolean result = file.mkdir(); //只能创建一个文件夹
        boolean result = file.mkdirs(); //创建多级文件夹
        System.out.println("创建文件夹:" + result);
        System.out.println("是否为文件夹:" + file.isDirectory());
        System.out.println("是否为文件:" + file.isFile());
    }
}

mkdir() 的时候,如果中间⽬录不存在,则⽆法创建成功; mkdirs() 可以解决这个问题。

2.3.6.观察文件重命名

import java.io.File;
import java.io.IOException;

public class FileDemo7 {
    public static void main(String[] args) throws IOException {
        //将a.txt -> 重命名为 -> f.txt
        File file = new File("a.txt");
        File tarFile = new File("f.txt");
        if(!file.exists()) {
            //先创建文件
            file.createNewFile();
        }
        //重命名文件
        boolean result = file.renameTo(tarFile);
        System.out.println("重命名结果:" + result);
    }
}

3.文件内容的读写——数据流

3.1.InputStream:输入流

InputStream输入流是用来读取数据的。

3.1.1.InputStream常用方法

修饰符及返回值类型
⽅法签名
说明
int
read()
读取⼀个字节的数据,返回 - 1代表已经完全读完了 (一个字节)
int
read(byte[] b)
最多读取 b.length 字节的数据到 b 中,返回实际读到的数 量;- 1 代表已经读完了 (所有字节)
int
read(byte[] b, int off, int len)
最多读取 len - off 字节的数据到 b 中,从 off 开始,返回 实际读到的数量;- 1 代表已经 读完了(部分字节)
void
close()
关闭字节流

InputStream 只是⼀个抽象类,要使⽤还需要具体的实现类。关于 InputStream 的实现类有很多,基本可以认为不同的输⼊设备都可以对应⼀个 InputStream 类,我们现在只关⼼从⽂件中读取,所以使⽤ FileInputStream。

3.1.2.FileInputStream

构造方法

签名说明
FileInputStream(File file)
利⽤ File 构造⽂件输⼊流
FileInputStream(String name)
利⽤⽂件路径构造⽂件输⼊流

读取文件中的内容

读取方式1

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class InputStreamDemo1 {
    public static void main(String[] args) {
        //1.创建流对象 try-catch
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream("c.txt");
            //2.读写操作
            while(true) {
                int c = inputStream.read();
                //如果流返回的是-1,说明数据已经读取完了
                if(c == -1) break;
                Thread.sleep(200);
                System.out.printf("%c", c);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException exception) {
            exception.printStackTrace();
        } finally {
            //3.关闭流
            if(inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

改进版:

import java.io.FileInputStream;
import java.io.InputStream;

public class InputStreamDemo2 {
    public static void main(String[] args) {
        //1.创建流对象 try-catch-resource(诞生于JDK1.7)
        try(InputStream inputStream = new FileInputStream("c.txt")) {
            //2.读写操作
            while(true) {
                int c = inputStream.read();
                //如果流返回的是-1,说明数据已经读取完了
                if(c == -1) break;
                Thread.sleep(200);
                System.out.printf("%c", c);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

读取方式2

import java.io.FileInputStream;
import java.io.InputStream;

/**
 * 一次性读取
 */
public class InputStreamDemo3 {
    public static void main(java.lang.String[] args) {
        try(InputStream inputStream = new FileInputStream("c.txt")) {
            byte[] bytes = new byte[1024];
            while(true) { //如果数据超过了byte容量,会读取多次
                int c = inputStream.read(bytes);
                if(c == -1) break;
                Thread.sleep(200);
                System.out.println(new String(bytes, "utf-8"));
            }
        } catch (Exception e) {
        }
    }
}

3.1.3.使用Scanner进行数据读取

构造方法说明
Scanner(InputStream is, String charset)
使⽤ charset 字符集进⾏ is 的扫描读取
import java.io.FileInputStream;
import java.util.Scanner;

public class InputStreamDemo4 {
    public static void main(String[] args) {
        try(FileInputStream inputStream = new FileInputStream("c.txt")) {
            try(Scanner scanner = new Scanner(inputStream, "utf8")) {
                while(scanner.hasNext()) {
                    System.out.println(scanner.nextLine());
                }
            }
        } catch (Exception e) {
        }
    }
}

3.2.OutputStream:输出流

OutputStream 输出流是进⾏数据写⼊的。

3.2.1.OutputStream 常用方法

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

OutputStream 同样只是⼀个抽象类,要使⽤还需要具体的实现类。我们现在还是只关⼼写⼊⽂件中,所以使⽤ FileOutputStream。

①一个字符一个字符写入

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class OutputStreamDemo1 {
    public static void main(String[] args) throws IOException {
        File file = new File("mytest.txt");
        if(!file.exists()) {
            //新建文件
            System.out.println("新建文件:" + file.createNewFile());
        }
        //文件写入操作
        try(OutputStream outputStream = new FileOutputStream(file)) {
            outputStream.write('H');
            outputStream.write('e');
            outputStream.write('l');
            outputStream.write('l');
            outputStream.write('o');
            outputStream.flush();
        }
    }
}

②字节数组批量写入

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class OutputStreamDemo2 {
    public static void main(String[] args) throws IOException {
        File file = new File("mytest.txt");
        if(!file.exists()) {
            file.createNewFile();
        }
        //写入操作
        try(OutputStream outputStream = new FileOutputStream(file)) {
            byte[] bytes = new byte[]{
                    'H', 'i'
            };
            outputStream.write(bytes);
            outputStream.flush();
        }
    }
}

写入部分数据

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class OutputStreamDemo2 {
    public static void main(String[] args) throws IOException {
        File file = new File("mytest.txt");
        if(!file.exists()) {
            file.createNewFile();
        }
        //写入操作
        try(OutputStream outputStream = new FileOutputStream(file)) {
            byte[] bytes = new byte[]{
                    'H', 'i', 'W', 'R', 'N'
            };
            //写入部分数据
            outputStream.write(bytes, 1, 3); //打印:iWR
            outputStream.flush();
        }
    }
}

③字符串写入

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;

public class OutputStreamDemo3 {
    public static void main(String[] args) throws IOException {
        File file = new File("mytest.txt");
        if(!file.exists()) {
            file.createNewFile();
        }
        //写入操作
        try(OutputStream outputStream = new FileOutputStream(file)) {
            String msg = "hello, world";
            outputStream.write(msg.getBytes(StandardCharsets.UTF_8));
            outputStream.flush();
        }
    }
}

3.2.3.使用 PrintWriter 进行写入

除了上述的写⼊⽅式之外,JDK 还提供了⼀个类 PrintWriter 可以很⽅便的实现数据写⼊。 PrintWriter 类中提供了我们熟悉的 print/println/printf ⽅法。

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;

public class OutputStreamDemo4 {
    public static void main(String[] args) throws IOException {
        File file = new File("mytest.txt");
        if(!file.exists()) file.createNewFile();
        try(PrintWriter printWriter = new PrintWriter(file)) {
            printWriter.println("这是第一行数据");
            printWriter.println("这是第二行数据");
            printWriter.printf("我叫:%s,今年:%d,至今未婚", "张三", 22);
            printWriter.flush();
        }
    }
}

以上都是覆盖数据。

3.2.4.使用FileWriter追加数据

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class OutputStreamDemo4 {
    public static void main(String[] args) throws IOException {
        File file = new File("mytest.txt");
        if(!file.exists()) file.createNewFile();

        //数据追加
        try(FileWriter fileWriter = new FileWriter(file, true)) { //传2个参数:第一个是要进行数据追加的文件,第二个是设置是否要进行数据追加,不写的话默认是false,不会追加数据
            fileWriter.append("我是追加的数据II\n");
            fileWriter.flush();
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值