文章导读
- 一、什么是文件
- 1、定义
- 2、主要部分
- 二、文件路径
- 1、绝对路径
- 2、相对路径
- 3、注意事项
- 三、Java中的文件操作
- 1、File 类
- 2、输入输出流
- 2.1、字节流
- InputStream 类
- FileInputStream
- 示例
- OutputStream
- FileOutputStream
- 2.2、字符流
- Reader 类
- Writer 类
一、什么是文件
1、定义
在计算机领域,文件是存储在存储设备(如硬盘、固态驱动器、闪存驱动器、光盘等)上的一组相关信息或数据的集合。这些信息或数据可以是文本、图像、音频、视频、程序指令、数据库记录等多种类型。文件是计算机操作系统管理数据的基本单位,允许用户和组织以逻辑方式存储、访问和修改信息。
2、主要部分
-
文件名:用于唯一标识文件的名称,通常由用户或程序指定。文件名可以包含字母、数字、空格和一些特殊字符,但具体规则取决于操作系统。
-
文件扩展名:位于文件名末尾的点(.)之后的部分,用于指示文件的类型或格式。例如,
.txt
表示文本文件,.jpg
表示JPEG格式的图像文件,.mp3
表示MP3格式的音频文件等。 -
文件内容:文件的实际数据或信息,可以是文本、二进制数据或其他形式的数据。
-
文件属性:除了文件名和扩展名之外,文件还包含一系列属性,如文件大小(占用的存储空间量)、创建日期和时间、修改日期和时间、访问日期和时间、文件权限(谁可以读取、写入或执行文件)等。
-
目录:为了将文件分类,操作系统提供了一类特殊的文件——目录(也叫文件夹),用以容纳各类的文件。目录也是文件,因此归属于同类的目录也可以放在统筹的目录中,形成嵌套式的树形结构,这样做使文件管理更加便利。
-
文件路径:用于定位文件在存储设备上的位置的信息。在大多数操作系统中,文件路径可以是绝对路径(从根目录开始的完整路径)或相对路径(相对于当前工作目录的路径)。
操作系统提供了文件管理功能,允许用户创建、打开、读取、写入、复制、移动、删除和重命名文件。这些操作通过文件系统实现,文件系统是操作系统中用于组织和存储文件的结构和机制。不同的操作系统可能支持不同的文件系统,如FAT、NTFS(Windows)、HFS+(Mac OS)、ext4(Linux)等。
二、文件路径
文件路径是文件在计算机存储系统中的位置表示,用于指向、定位或访问文件。它通常由目录(或文件夹)名和文件名组成,目录和目录之间、目录和文件名之间使用特定的分隔符(如在Windows系统中是反斜杠\
,在Unix、Linux及MacOS系统中是正斜杠/
)分隔。文件路径可以是绝对路径或相对路径。
1、绝对路径
绝对路径是从根目录(或称为顶级目录)开始的完整路径。它包含了从根目录到目标文件所需经过的所有目录和子目录的完整列表,因此,无论当前工作目录是什么,使用绝对路径都可以定位到文件。
例子(Windows):
C:\Users\Username\Documents\file.txt
这里,C:
是根目录(驱动器),\Users\Username\Documents\
是从根目录到文件所在目录的路径,file.txt
是文件名。
例子(Unix/Linux/MacOS):
/home/username/documents/file.txt
这里,/
是根目录,/home/username/documents/
是从根目录到文件所在目录的路径,file.txt
是文件名。
2、相对路径
相对路径是从当前工作目录(或称为当前目录)开始到目标文件的路径。它不包含从根目录到当前目录的完整路径,因此,相对路径的有效性取决于当前工作目录。
例子(Windows):
如果当前工作目录是 C:\Users\Username\Documents
,则相对路径 .\file.txt
或仅 file.txt
都可以指向 C:\Users\Username\Documents\file.txt
。
例子(Unix/Linux/MacOS):
如果当前工作目录是 /home/username/documents
,则相对路径 ./file.txt
或仅 file.txt
都可以指向 /home/username/documents/file.txt
。
注意,.
表示当前目录,..
表示上一级目录。因此,相对路径可以使用 ..
来向上回溯目录结构。
3、注意事项
- 路径中的大小写敏感性取决于操作系统。Windows通常不区分大小写,而Unix、Linux和MacOS则区分大小写。
- 路径中的空格和特殊字符可能需要特殊处理,如在命令行中使用时可能需要用引号括起来或进行转义。
- 目前window系统也支持使用
/
作为分隔符。
三、Java中的文件操作
1、File 类
-
构造方法
构造方法 描述 File(String pathname) 通过给定的路径名字符串 (可以是绝对路径或相对路径)来创建新的 File
实例。File(String parent, String child) 根据父路径名字符串和子路径名字符串来创建新的 File
实例。如果父路径名为null
,则新创建的File
实例将使用绝对路径名child
。File(File parent, String child) 根据 File
对象表示的父目录和子路径名字符串来创建新的File
实例。这允许你基于已经存在的File
对象来构建新的路径。File(URI uri) 通过将给定的 file:
URI 转换为抽象路径名来创建新的File
实例。注意,这里的 URI 必须是file:
协议的 URI,否则将抛出IllegalArgumentException
。请注意,这些构造方法中的路径名或 URI 指定的文件或目录不需要实际存在;
File
对象仅表示一个路径名。你可以使用File
类提供的方法来检查文件或目录是否存在,或者执行其他与文件或目录相关的操作。 -
常见方法
以下是用表格形式列举的File
类的常见方法,这些方法在Java中用于操作文件和目录:方法名 描述 返回值类型 备注 exists()
检查文件或目录是否存在 boolean
如果文件或目录存在,则返回 true
isFile()
判断File对象是否表示一个文件(而不是目录) boolean
如果是文件,则返回 true
isDirectory()
判断File对象是否表示一个目录 boolean
如果是目录,则返回 true
getName()
返回文件或目录的名称 String
返回路径名中的最后一部分 getParent()
返回文件或目录的父路径名字符串 String
如果没有父目录,则返回 null
getPath()
返回文件或目录的路径名字符串 String
返回创建 File
对象时使用的路径名getAbsolutePath()
返回文件或目录的绝对路径名字符串 String
解析为绝对路径名 createNewFile()
创建新文件,如果文件已存在则不创建 boolean
如果文件创建成功,则返回 true
delete()
删除文件或目录 boolean
如果删除成功,则返回 true
mkdir()
创建目录 boolean
如果目录创建成功,则返回 true
mkdirs()
创建目录,包括所有必需的父目录 boolean
如果目录创建成功,则返回 true
length()
返回文件的大小(以字节为单位) long
如果文件不存在,则返回 0L
list()
返回目录中的文件和目录名字符串数组 String[]
调用此方法的File对象必须表示一个目录 listFiles()
返回目录中的文件和目录 File
对象数组File[]
调用此方法的File对象必须表示一个目录 lastModified()
返回文件或目录的最后修改时间 long
以毫秒为单位,自1970年1月1日00:00:00 GMT以来的时间 canRead()
判断文件或目录是否可读 boolean
取决于Java虚拟机的安全管理器 canWrite()
判断文件或目录是否可写 boolean
取决于Java虚拟机的安全管理器 isHidden()
判断文件或目录是否为隐藏文件或目录 boolean
在某些操作系统中,隐藏文件或目录可能不被列出 renameTo(File dest)
重命名文件或目录 boolean
如果重命名成功,则返回 true
getCanonicalPath()
返回File对象的修饰过的绝对路径 String
它消除了路径名中的冗余名称(如 .
和..
),并将路径分隔符解析为适当的分隔符(在 UNIX 系统中是/
,在 Windows 系统中是\
)deleteOnExit()
根据File对象,标注⽂件将被删除,删除动作会到JVM运⾏结束时才会进行 void
请注意,上述方法中的大多数都可能会抛出
SecurityException
,如果安全管理器存在并且其checkRead
、checkWrite
、checkDelete
或checkExec
方法不允许进行指定的操作。此外,一些方法(如createNewFile()
、delete()
等)还可能抛出IOException
,但File
类本身的方法通常不会直接读取或写入文件内容,因此这些异常通常不会由File
类的方法直接抛出。然而,当与FileInputStream
、FileOutputStream
等类结合使用时,可能会遇到IOException
。
2、输入输出流
数据流(data stream)是一组有序、有起点和终点的字节数据序列,包括输入流和输出流。
- 输入流是指从某个数据源(如文件、键盘、网络等)读取数据的通道。当程序需要从外部世界获取数据时,就会使用输入流。输入流允许程序以顺序的方式读取数据,直到到达数据源的末尾。
- 输出流是指将数据写入到某个目的地(如文件、屏幕、网络等)的通道。当程序需要将数据发送到外部世界时,就会使用输出流。输出流允许程序以顺序的方式写入数据,直到数据被完全写入目的地。
在输入输出流也分为字节流和字符流两部分。
2.1、字节流
字节流(Byte Stream)是计算机中一种基本的数据传输方式,它是以字节(Byte)为单位的有序序列。在计算机系统中,所有数据最终都以字节的形式进行表示、存储和传输,因此字节流是处理这些数据的基础。
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
。
FileInputStream
- 构造函数
方法签名 | 说明 |
---|---|
FileInputStream( Filefile ) | 利用File构造⽂件输⼊流 |
FileInputStream( String path) | 利用文件路径构造⽂件输⼊流 |
示例
以下是两种 读的方法,第二种方法效率更高。
public class Main {//需要先在项⽬⽬录下准备好⼀个hello.txt的⽂件,⾥⾯填充"Hello"的内容public static void main(String[] args) throws IOException {try (InputStream is = new FileInputStream("hello.txt")) {while (true) {int b = is.read();if (b == -1) {//代表⽂件已经全部读完break;}System.out.printf("%c", b);}}}
}
//需要先在项⽬⽬录下准备好⼀个hello.txt的⽂件,⾥⾯填充 "Hello" 的内容public class Main {public static void main(String[] args) throws IOException {try (InputStream is = new FileInputStream("hello.txt")) {byte[] buf = new byte[1024];int len;while (true) {len = is.read(buf);if (len == -1) {//代表⽂件已经全部读完break;}for (int i = 0; i < len; i++) {System.out.printf("%c", buf[i]);}}}}
}
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( ) 重要:我们知道I/O的速度是很慢的,所以,大多的OutputStream为了减少设备操作的次数,在写数据的时候都会将数据先暂时写入内存的⼀个指定区域⾥,直到该区域满了或者其他指定条件时才真正将数据写⼊设备中,这个区域⼀般称为缓冲区。但造成⼀个结果,就是我们写的数据,很可能会遗留⼀部分在缓冲区中。需要在最后或者合适的位置,调用 flush(刷新)操作,将数据刷到设备中。 -
说明
OutputStream 同样只是⼀个抽象类,要使用还需要具体的实现类。我们现在还是只关心写⼊⽂件中,所以使FileOutputStream
。
FileOutputStream
-
构造函数
方法签名 说明 FileOutputStream( Filefile ) 利用File构造⽂件输出流 FileOutputStream( String path) 利用文件路径构造⽂件输出流 -
示例
示例1
import java.io.*;public class Main {public static void main(String[] args) throws IOException {try (OutputStream os = new FileOutputStream("output.txt")) {os.write('H');os.write('e');os.write('l');os.write('l');os.write('o');// 不要忘记flushos.flush();}}}
2.2、字符流
字符流(Character Stream)是由一系列连续的字符组成的集合,它主要用于处理文本数据。
Reader 类
FileReader
是Reader
类的一个子类,用于从文件中读取字符数据。以下是一个使用FileReader
读取文件内容并输出到控制台的例子:
import java.io.FileReader;
import java.io.IOException;public class FileReaderExample {public static void main(String[] args) {FileReader fileReader = null;try {// 创建FileReader对象,指定要读取的文件路径fileReader = new FileReader("input.txt");int data;// 读取文件中的字符,直到文件末尾while ((data = fileReader.read()) != -1) {// 将读取到的字符转换为int类型,并强制转换为char类型后输出System.out.print((char) data);}} catch (IOException e) {e.printStackTrace();} finally {// 关闭流资源if (fileReader != null) {try {fileReader.close();} catch (IOException e) {e.printStackTrace();}}}}
}
`
Writer 类
-
FileWriter
是Writer
类的一个子类,用于向文件中写入字符数据。以下是一个使用FileWriter
将数据写入到文件的例子:import java.io.FileWriter; import java.io.IOException;public class FileWriterExample {public static void main(String[] args) {FileWriter fileWriter = null;try {// 创建FileWriter对象,指定要写入的文件路径fileWriter = new FileWriter("output.txt");// 写入字符串到文件fileWriter.write("Hello, World!");// 强制刷新缓冲区中的数据到文件中fileWriter.flush();} catch (IOException e) {e.printStackTrace();} finally {// 关闭流资源if (fileWriter != null) {try {fileWriter.close();} catch (IOException e) {e.printStackTrace();}}}} }
-
BufferedReader
和BufferedWriter
分别是Reader
和Writer
的子类,它们通过内部缓冲区来提高字符流的读写效率。以下是一个使用BufferedReader
读取文件和BufferedWriter
写入文件的例子:import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException;public class BufferedStreamsExample {public static void main(String[] args) {BufferedReader br = null;BufferedWriter bw = null;try {// 读取文件br = new BufferedReader(new FileReader("input.txt"));// 写入文件bw = new BufferedWriter(new FileWriter("output.txt"));String line;// 逐行读取并写入while ((line = br.readLine()) != null) {bw.write(line);bw.newLine(); // 添加新行}
-
FileWriter
的构造方法还允许在文件末尾追加数据,而不是覆盖原有数据。以下是一个使用FileWriter
追加数据到文件的例子:import java.io.FileWriter; import java.io.IOException;public class FileWriterAppendExample {public static void main(String[] args) {FileWriter fileWriter = null;try {// 创建FileWriter对象,指定要写入的文件路径,并设置append模式为truefileWriter = new FileWriter("output.txt", true);// 追加字符串到文件fileWriter.write("\nNew line appended.");// 强制刷新缓冲区中的数据到文件中fileWriter.flush();} catch (IOException e) {e.printStackTrace();} finally {// 关闭流资源if (fileWriter != null) {try {fileWriter.close();} catch (IOException e) {e.printStackTrace();}}}} }