浅谈⽂件操作和IO
目录
1 什么是文件
2 文件的管理方式
3 文件系统存储的文件
4 文件系统操作
File概述
代码示例
5 文件内容操作
1 什么是文件
文件是在硬盘上存储数据的一种方式. 操作系统帮我们把硬盘的一些细节都封装起来了. 程序猿只需要了解文件相关的接口即可. 而硬盘用来存储数据的, 和内存相比, 硬盘的存储空间更大, 访问速度更慢, 成本更低, 是一种持久化存储. 操作系统通过"文件系统"这样的模块来管理硬盘.
可能你的电脑上面有好几个盘, 但实际上我们的电脑上只有一个硬盘, 是操作系统通过文件系统把这一个硬盘抽象成多个硬盘.
NTFS windows 上的文件系统,背后有一定的格式来组织硬盘的数.
EXT4 Linux上常见的文件系统.
2 文件的管理方式
不同的文件系统,管理文件的方式都是类似的, 都是通过目录 - 文件的形式构成 "N叉树" 树形结构.
directory 目录/文件夹
3 文件系统存储的文件
文件系统上存储的文件, 具体来说又分成两个大类.
1. 文本文件, 存储的是字符.
2. 二进制文件, 存储的是二进制的数据.
怎么判断文件是文本文件还是二进制文件呢?
一个最简单的方式就是你用记事本打开, 如果能看懂就是文本文件, 看不懂的就是二进制文件.
记事本打开文件, 就是尝试把当前的数据在码表中进行查询.
word 文档这种, 你在里面写上一句hello world, 在放到记事本中打开, 会出现你看不懂的信息, 这是因为word文档里面其实是包含很多信息的. word这种称为"富文本".
4 文件系统操作
后续针对文件的操作,文本和二进制, 它们的操作方式是完全不同的.
Java中通过 java.io.File 类来对⼀个⽂件(包括⽬录)进⾏抽象的描述。注意,有File对象, 并不代表真实存在该⽂件。
File概述
我们先来看看 File 类中的常⻅属性、构造⽅法和⽅法
属性
构造⽅法
⽅法
代码示例
示例1 观察get系列的特点和差异
public class Demo1 {
public static void main(String[] args) throws IOException, IOException {
File file = new File("./test.txt");
System.out.println(file.getParent());
System.out.println(file.getName());
System.out.println(file.getPath());
System.out.println(file.getAbsolutePath());
System.out.println(file.getCanonicalPath());
}
}
⽰例2 普通⽂件的创建、删除
// 文件创建
public class Demo2 {
public static void main(String[] args) throws IOException, IOException {
File file = new File("./test.txt");
// 创建文件
file.createNewFile();
System.out.println(file.exists());
System.out.println(file.isFile());
System.out.println(file.isDirectory());
}
}
// 文件删除
public class Demo3 {
public static void main(String[] args) throws InterruptedException {
File file = new File("./test.txt");
// file.delete();
// 是等到程序退出了再删除, 不是立即删除
file.deleteOnExit();
Thread.sleep(5000);
}
}
示例3 观察⽬录的创建
//创建目录
public class Demo4 {
public static void main(String[] args) {
File file = new File("./testDir/111/222/333");
// mk => make dir => directory
// mkdir 一次只能创建一层目录. mkdirs 可以一次创建多级目录
// file.mkdir();
file.mkdirs();
}
}
示例4 文件重命名
先创建文件
再给文件重命名, 同时也有了移动的效果.
以上文件系统的操作都是基于File类完成的.
5 文件内容操作
Reader的使用
// Reader的使用
public class Demo6 {
public static void main(String[] args) throws IOException {
/*// FileReader 构造方法, 可以填写一个文件路径(绝对路径/相对路径都行), 也可以填写一个构造好的 File 对象
Reader reader = new FileReader("./test.txt");
try {
// 中间的代码无论出现啥情况, close 都能保证执行到.
}finally {
// 抛出异常, 或者 return, close 就都执行不到了~~
reader.close();;
}*/
// 上述使用 finally 的方式能解决问题, 但是不优雅.
// 使用 try with resources 是更好的解决方案.
try(Reader reader = new FileReader("./test.txt")) {
}
}
}
try(Reader reader = new FileReader("c:/code/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.print(buf[i] + ",");
}
}
}
InputStream的使用
lnputStream是字节流, 用法和Reader非常相似. 文本文件, 也可以使用字节流打开. 只不过此时你读到的每个字节, 就不是完整字符了.
// inputStream的使用
public class Demo7 {
public static void main(String[] args) throws IOException {
try(InputStream inputStream = new FileInputStream("c:/code/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.printf("%x ", buf[i]);
}
}
}
}
}
此处借助String, String构造方法内部对字节数组进行了编码转换.
利⽤Scanner进⾏字符读取
// Scanner读取文件
public class Demo8 {
public static void main(String[] args) throws IOException {
try (InputStream inputStream = new FileInputStream("c:/code/test.txt")) {
// 此时就是从 test.txt 这个文件中读取数据了!!
Scanner scanner = new Scanner(inputStream);
String s = scanner.next();
System.out.println(s);
}
}
}
Writer的使用
//Writer的使用
public class Demo9 {
public static void main(String[] args) throws IOException {
try(Writer writer = new FileWriter("c:/code/test.txt", true)) {
// write 是可以一次直接写一个字符串. 这个是非常方便的.
writer.write("hello java");
}
}
}
OutputStream的使用
//OutputStream的使用
public class Demo10 {
public static void main(String[] args) throws IOException {
try(OutputStream outputStream = new FileOutputStream("c:/code/test.txt", true)) {
outputStream.write(111);
}
}
}