文件介绍
文件本身有多重含义,狭义的文件,特指硬盘上的文件(以及保存文件的目录) ,广义的文件:计算机上的很多硬件设备,软件资源,在操作系统中,都会被视为是"文件"
文件除了有数据内容之外,还有一部分信息,例如文件名,文件类型,文件大小,这些信息可以称作文件的元信息
树型结构组织和目录
在一个电脑上,有很多文件,文件数量太多,所以要对文件进行系统管理,操作系统专门有一个模块-"文件系统 ",一般是通过"文件资源管理器"观察到文件系统管理的文件.
进行文件的组织,采用了层级结构 进行组织,也就是树型结构(n叉树) ,一种专门用来存放管理信息的特殊文件,即文件夹或者目录.
文件夹/目录 中保存的就是关于文件的元信息
文件路径
如何在文件系统中定位唯一一个文件呢?
从树型结构的角度来看,树中的每个结点都可以被一条从根开始,一直到达的结点的路径所描述,这种描述方式就称为文件的绝对路径
例:
C:\Intel\iGfx\Vulkan
除了可以从根开始进行路径的描述,我们可以从任意结点出发,进行路径的描述,这种描述方式就被称为相对路径
相对路径可以是以下几种形式:
- 相对于当前目录:使用文件名或目录名即可,不需要任何前缀。例如,如果当前目录是 "/home/user",要引用同一目录下的 "file.txt",可以使用相对路径 "file.txt"。
- 相对于上级目录:使用 "../" 表示上级目录。例如,要引用上级目录中的文件 "parentfile.txt",可以使用相对路径 "../parentfile.txt"。
- 相对于任意目录:使用若干个 "../" 组合表示相对于当前目录的某一级别的上级目录。例如,要引用当前目录的上一级目录的子目录 "subdir" 下的文件 "subfile.txt",可以使用相对路径 "../../subdir/subfile.txt"。
文件属性
即使是普通文件,根据其保存数据的不同,我们一般简单的划分为文本文件和二进制文件
-
文本文件: 文本文件是以文本形式存储数据的文件。它由字符组成,每个字符都使用特定的编码方式表示。常见的文本文件格式包括TXT、CSV等。文本文件可以使用文本编辑器打开,并且可以直接阅读和编辑其中的内容。文本文件中的数据通常是以行为单位进行组织,每行数据可以包含字母、数字、符号等。
-
二进制文件: 二进制文件是以二进制形式存储数据的文件。它不是以字符的形式存在,而是以字节的形式存储。二进制文件可以包含任意类型的数据,如图片、音频、视频、程序等。二进制文件的内容无法直接阅读或编辑,需要使用特定的程序或工具进行解析和处理。二进制文件通常是使用特定的格式进行编码和存储,如JPEG、MP3、EXE等。
区别:
- 存储方式:文本文件以字符形式存储,二进制文件以字节形式存储。
- 可读性:文本文件内容可以直接阅读和编辑,而二进制文件内容通常需要特定的工具进行解析和处理。
- 文件大小:由于文本文件只存储字符,而二进制文件可以存储任意类型的数据,所以相同数据量下,二进制文件通常比文本文件更小。
- 处理效率:由于文本文件内容可以直接读取和处理,所以在某些情况下,处理文本文件可能更加高效。
文件操作
Java操作文件,通过 java.io.File 类来对一个文件(包括目录)进行抽象的描述.
1.文件系统操作
File类
属性
修饰符及类型 | 属性 | 说明 |
---|---|---|
static String | pathSeparator | 依赖于系统的路径分隔符,String类型表示 |
static char | pathSeparator | 依赖于系统的路径分隔符,char类型的表示 |
构造方法
方法 | 说明 |
---|---|
File(File parent,String child) | 根据父目录+孩子文件路径,创建一个新的File实例 |
File(String pathname) | 根据文件路径创建一个新的File实例,路径可以是绝对路径或者相对路径 |
File(String parent,String child) | 根据父目录+孩子文件路径,创建一个新的File实例,父目录用路径表示 |
方法
修饰符及返回值类型 | 方法签名 | 说明 |
---|---|---|
String | getParent() | 返回FIle对象的父目录文件路径 |
String | getName() | 返回File对象的纯文件名称 |
Strng | getPath() | 返回File对象的文件路径 |
String | gerAbsolutePath() | 返回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() | 判断用户是否对文件有可写权限 |
示例
1.获取文件相关信息
java
public static void main(String[] args) throws IOException {
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.getAbsolutePath());
System.out.println(file.getCanonicalPath());
}
/**
* 输出
* .
* text.txt
* .\text.txt
* D:\LXY_Java\javaa\Thread\.\text.txt
* D:\LXY_Java\javaa\Thread\text.txt
*/
2.创建新文件:
java
public static void main(String[] args) throws IOException {
File file = new File("./test.txt");
boolean ok = file.createNewFile();
System.out.println(ok);
System.out.println(file.exists());
System.out.println(file.isFile());
System.out.println(file.isDirectory());
}
/**
* false
* true
* true
* false
*/
3.删除文件:
java
public static void main(String[] args) {
File file = new File("./test.txt");
boolean ok = file.delete();
System.out.println(ok);
}
//true
public static void main(String[] args) {
File file = new File("./test.txt");
file.deleteOnExit();
System.out.println("执行删除完毕");
Scanner scanner = new Scanner(System.in);
scanner.next();
}
4.创建目录:
java
public static void main(String[] args) {
File f = new File("./abc/def/ghi");
boolean ok = f.mkdirs();
System.out.println(ok);
}
5.重命名
java
public static void main(String[] args) {
File srcFile = new File("./abc/def");
File destDile = new File("./aaa");
boolean ok = srcFile.renameTo(destDile);
System.out.println(ok);
}
2.文件内容操作
数据流
数据流(Data Streams)是在程序中进行数据输入和输出的一种方式。数据流主要用于处理基本数据类型和对象的序列化和反序列化操作。
在Java中,数据流主要包括了两种类型:字节流和字符流。
字节流(Byte Streams) 用于处理二进制数据 ,以字节(byte)为单位进行读取和写入。常见的字节流类有InputStream和OutputStream。
字符流(Character Streams) 用于处理文本数据 ,以字符(char)为单位进行读取和写入。常见的字符流类有Reader和Writer。
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 的子类对象,如 FileInputStream,用于打开要读取的文件。
- 调用 InputStream 对象的 read()、read(byte[] b)、read(byte[] b, int off, int len) 方法读取字节数据。
- 处理读取到的数据。
- 关闭 InputStream 对象,释放资源,使用 close() 方法。
FileInputStream
方法 | 说明 |
---|---|
FileInputStream(File file) | 利用File构造文件输入流 |
FileInputStream(String name) | 利用文件路径构造文件输入流 |
利用Scanner进行字符读取
构造方法 | 说明 |
---|---|
Scanner(InputStream is,String charset) | 使用charset字符集进行is的扫描读取 |
示例
读取文件两种方式
上述图中
- read():调用一次读一个字节
- read(byte[] b,int off,int len):一次读取 b 中 [off,off+len)范围的区间
- read(byte[] b):一次读取 b 中所有字节
java
public static void main(String[] args) {
try(InputStream inputStream = new FileInputStream("./test.txt")){
while(true){
int b = inputStream.read();
if(b==-1){
//读取完毕
break;
}
//表示字节更习惯用16进制表现
System.out.printf("0x%x\n",b);
}
}catch (IOException e){
e.printStackTrace();
}
}
java
public static void main(String[] args) {
try(InputStream inputStream = new FileInputStream("./test.txt")){
while(true){
byte[] buffer = new byte[1024];
//n返回值表示read实际读取到
int n = inputStream.read(buffer);
if(n==-1){
break;
}
for (int i = 0; i < n; i++) {
System.out.printf("0x%x\n",buffer[i]);
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
使用scanner
java
public static void main(String[] args) throws IOException {
try (InputStream is = new FileInputStream("test.txt")) {
try (Scanner scanner = new Scanner(is, "UTF-8")) {
while (scanner.hasNext()) {
String s = scanner.next();
System.out.print(s);
}
}
}
}
OutputStream
方法
修饰符及返回值类型 | 方法 | 说明 |
---|---|---|
void | write(int b) | 写入要给字节的数据 |
void | write(byte[] b) | 将b这个字符数组中的数据全部写入 os 中 |
int | write(byte[] b, int off, int len) | 将 b 这个字符数组中从off开始的数据写入os中,一共写len个 |
void | close() | 关闭字节流 |
void | flush() | 刷新输出流的缓冲区,将缓冲区中的数据立即写入到输出目的地中,而不是等待缓冲区满或者流关闭 |
示例
java
public static void main(String[] args) {
try(OutputStream outputStream = new FileOutputStream("./test.txt",true)){
outputStream.write(0xe4);
outputStream.write(0xbd);
outputStream.write(0xa0);
outputStream.write(0xe5);
outputStream.write(0xa5);
outputStream.write(0xbd);
outputStream.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//hello
Reader和Writer
Reader和Writer与InputStream和OutputStream类似,区别就是Reader和Writer以字符(char)为单位进行读取和写入
java
public static void main(String[] args) {
try(Reader reader = new FileReader("./test.txt")){
char[] buffer = new char[1024];
int n = reader.read(buffer);
System.out.println(n);
for (int i = 0; i < n; i++) {
System.out.println(buffer[i]);
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
java
public static void main(String[] args) {
try(Writer writer = new FileWriter("./test.txt",true)){
writer.write("你好世界");
} catch (IOException e) {
throw new RuntimeException(e);
}
}