目录
文件
1. 认识文件
// 在硬盘上存储数据的方式
// 针对硬盘这种持久化存储的 I/O 设备, 当我们想要进行数据保存时, 往往不是保存成一个整体, 而是独立成一个个的单位进行保存, 这的独立的单位就被抽象成文件的概念
// 文件除了有数据内容之外, 还有一部分信息, 例如 文件名, 文件类型, 文件大小 等并不作为文件的数据而存在, 我们把这部分信息可以视为文件的元信息
2. 树型结构组织和目录
// 随着文件越来越多, 就采用层级结构 (树形结构)对文件进行组织, 这样, 一种专门用来存放管理信息的特殊文件就诞生了, 也就是我们平时说的 文件夹 (folder) 或 目录 (directory) 的概念
3. 文件路径 (Path)
// " \ 或者 / "被称为路径分隔符
// 从树形结构来看, 树中每个节点都可以被一条从根出发, 一直到达该结点的路径所描述, 这种描述方式就被称为文件的绝对路径 (absolute path), 绝对路径相当于是从 "此电脑这里出发", 找到文件的过程
// 除了从根开始进行路径的描述, 我们可以从任意结点出发, 进行路径的描述, 而这种描述方式就被称为相对路径 (relative path), 相对于当前所在结点的一条路径, 相对路径需要有一个 "基准目录" / "工作目录", 表示从这个基准目录出发, 怎么走能找到这个文件(以. 或 .. 出发的, 其中 . 当前目录, .. 表示当前目录的上一层目录)
// 同样一个文件, 站在不同的基准目录上, 查找的路径是不相同的!
4. 文件系统上存储的文件又可以分为两大类
4.1 文本文件
// 存储的是字符 (utf8 就是一个大表, 这个表上的数据组合就可以称为是字符)
4.2 二进制文件
// 存储二进制的数据
// 如何判断是哪一类? 直接使用记事本打开, 如果能看懂, 就是文本文件, 看不懂就是二进制文件
文件系统操作
1.Java 中操作文件
// 通过 java.io.File 类来对一个文件(包括目录) 进行抽象的描述
// IO input 和 output (我们都是站在 cpu 的角度来描述输入输出的)
// File对象可以对应到一个真实存在的文件, 也可以对应一个不存在的文件
2. File 概述
2.1 属性
修饰符及类型 | 属性 | 说明 |
static String | pathSeparator | 依赖于系统的路径分隔符, String 类型的表示 |
static char | pathSeparator | 依赖于系统的路径分隔符, char 类型的表示 |
2.2 构造方法
签名 | 说明 |
File(File parent, String child) | 根据父目录 + 孩子文件路径, 创建一个新的 File 实例 |
File(String pathname) | 根据文件路径创建一个新的 File 实例, 路径可以是绝对路径或者相对路径 |
File(String parent, String child) | 根据父目录 + 孩子文件路径, 创建一个新的 File 实例, 父目录用路径表示 |
2.3 方法
修饰符及返回值类型 | 方法签名 | 说明 |
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.4 部分举例
// 绝对路径
public static void main(String[] args) throws IOException {
File file = new File("d:/test.txt");
System.out.println(file.getParent());
System.out.println(file.getPath());
System.out.println(file.getName());
System.out.println(file.getAbsolutePath());
System.out.println(file.getCanonicalPath());
}
// 相对路径
public static void main(String[] args) throws IOException {
File file = new File("./test.txt");
System.out.println(file.getParent());
System.out.println(file.getPath());
System.out.println(file.getName());
System.out.println(file.getAbsolutePath());
System.out.println(file.getCanonicalPath());
}
public static void main(String[] args) {
File file = new File("./ text.txt");
System.out.println(file.exists());
System.out.println(file.isFile());
System.out.println(file.isDirectory());
}
// 创建文件后继续查询
public static void main(String[] args) throws IOException {
File file = new File("./ text.txt");
file.createNewFile();
System.out.println(file.exists());
System.out.println(file.isFile());
System.out.println(file.isDirectory());
}
// 这样创建文件时可能会抛出异常, 比如当前写入的路径是非法的或者创建文件时, 对于所在目录没有权限操作
public static void main(String[] args) throws InterruptedException {
File file = new File("./ text.txt");
// file.delete(); 这个是立即删除
file.deleteOnExit(); // 这个是等退出程序时删除
Thread.sleep(5000);
}
public static void main(String[] args) {
File file = new File("./ testDir");
file.mkdir();
// file.mkdirs();
}
// 通过这个创建命令, 我们就可以穿件新的目录, mkdir 只能创建一层目录, mkdirs 可以创建多层
// 文件系统的操作都是基于 File 类来实现的
文件内容操作
1. 数据流(文件流) Stream
2. 文件内容的操作核心步骤:
2.1 打开文件
2.2 关闭文件
// close 操作非常重要, 用来释放必要的资源, 如果不释放, 就会出现 "文件资源泄露" 很严重的问题
2.3 读文件
try (Reader reader = new FileReader("d:/test.txt")){
while (true) {
char buf[] = new char[1024];
int n = reader.read(buf);
if (n == -1) {
// 读到末尾了
break;
}
for (int i = 0; i < n; i++) {
System.out.println(buf[i] + " ");
}
}
}
public static void main(String[] args) throws IOException {
try(InputStream inputStream = new FileInputStream("d:/test.txt")) {
while (true) {
byte[] buf = new byte[1024];
int n = inputStream.read(buf);
if (n == -1) {
break;
}
for (int i = 0; i < n; i++) {
System.out.println("%x ", buf[i]);
}
}
}
2.4 写文件
public static void main(String[] args) throws IOException {
try (Writer writer = new FileWriter("d:/test.txt",true)){
writer.write("hello java");
}
}
// 不加 true 的话, 默认会清空原有内容之后写入, 加上之后就会在原有内容后面继续写入
3. Java中是通过一系列类来实现的
3.1 字节流
3.1.1 InputStream
public static void main(String[] args) throws IOException {
try(InputStream inputStream = new FileInputStream("d:/test.txt")) {
Scanner scanner = new Scanner(inputStream);
String s = scanner.next();
System.out.println(s);
}
}
// Scanner 只是用来读文本文件, 不适合读取二进制文件
3.1.2 OutputStream
// 使用方法和 write 方法完全一样, 只不过 write 方法不能支持 字符串 参数, 只能按照 字节, 或者 字节数组来写入
// 后续的一些操作字节的类都是衍生自这两个类
// 是操作字节为单位 (二进制文件)
3.2 字符流
3.2.1 Reader
public static void main(String[] args) throws IOException {
// FileReader 构造方法, 可以填写一个文件路径(绝对路径/相对路径都行), 也可以填写一个构造好的 File 对象
// Reader reader = new FileReader("d:/test.txt");
// try {
// // 中间的代码无论如何变化, 最后 close 一定会执行
// }finally {
// reader.close();
// }
// 也可以用下面这种更好的方法(try with resources), 来解决问题
try (Reader reader = new FileReader("d:/test.txt")){
// 这个就完成了打开文件操作
}
}
3.2.2 Writer
public static void main(String[] args) throws IOException {
try (Writer writer = new FileWriter("d:/test.txt",true)){
writer.write("hello java");
}
}
// 后续操作字符的类, 衍生自这两个类
// 是操作字符为单位 (文本文件)
// Java IO 流是一个比较庞大的体系, 涉及到非常多的类, 这些不同类, 都有各自不同的特性, 但总的来说, 使用方法都是类似的
// 1) 构造方法, 打开文件
// 2) close 方法, 关闭文件
// 3) 如果衍生自 InputStream 或者 Read, 就可以使用 read 方法来读数据
// 4) 如果衍生自 OutputStream 或者 Writer, 就可以使用 write 方法来写数据了