文件操作及读写-爪哇版
文章目录
- 前言
- 初识文件
- 文件路径里的符号
- 文件分类
- 文件操作方法
- 文件读写
- 字节流输入输出
- 输入
- 输出
- 字符流输入输出
- 输入
- 输出
前言
Windows用户需知:“/”和“\”, 文件路径分隔符一般都用“/”,但Windows系统一直保留着“\”,这两种符号都可用于Windows系统文件分隔符,但由于使用字符串来表示路径,使用“\”还得转义,所以推荐用“/”。在观看本文时,将“/”和“\”看做一种符号即可,以免扰乱思路。
初识文件
计算机里的文件是以目录+树形结构管理的,每一个文件都有其唯一的路径来定位其存储位置,分为:
- 绝对路径:从根节点到当前节点的路径,例如"C:/Programfiles/java/jdk-17/bin/java.exe",从根节点定位到当前节点。
- 相对路径:从任意节点到当前节点的路径,例如"./jdk-17",以当前目录为基准目录,相对于这个基准目录的路径。基准目录是哪个得看程序运行在哪个目录下。
文件路径里的符号
“.”和“…”:“./”代表当前节点/目录,./test.txt代表在当前目录下的text.txt相对路径,“…”代表当前节点/目录的父节点/目录,"…/./test.txt”则定位到了当前节点的父节点,如果要定位父节点的父节点的。。。应该用“…/…/…/等等。。。”而不是“…等等。。。/”。
文件分类
文件分为文本文件和二进制文件,但二者本质都是二进制文件(实质内容都是一大串二进制数据)。
文本文件:文件的二进制数据可以直接用字符编码集(Unicode、ASCII等)翻译为字符,文件用记事本打开可以直接翻译为有效字符。常见文件类型的有.txt、.java、.html等。
二进制文件: 不可以直接用字符编码集翻译为字符,需用指定的方式解析为有效数据,使用计算机打卡是一堆乱码。常见的文件类型有.jpg、.mov、.mp4等。
文件操作方法
为减少文章冗余,把方法练习示例放在另一处:方法练习示例链接
方法名 | 用法 |
---|---|
FIle(String path) | 创建文件实例,path可以是绝对路径也可以是相对路径 |
File(File parent, String path) | 根据父目录和孩子路径,创建一个实例 |
File(String parent,String path) | 根据父目录路径和孩子路径,创建一个实例 |
getName() | 返回文件对象代表的文件的名称 |
getParent() | 返回文件对象代表的文件的父目录名称 |
getPath() | 返回文件对象代表的文件的相对路径 |
getAbsolutePath() | 返回文件对象代表的文件的绝对路径 |
getCanonicalPath() | 返回文件对象代表的文件的绝对路径(过滤了字符串中的".“和”…") |
exists() | 判断文件是否存在 |
isFile() | 当前是不是一个普通文件 |
isDirectory() | 判断是不是一个目录 |
canRead() | 判断当前用户对该文件是否有读权限 |
canWrite() | 判断当前用户对该文件是否有写权限 |
文件读写
我们对数据输入输出的状态形象的称为流,在数据输入输出的时候,连绵不断的0、1数据像水流一样来回运输,于是就有了输入流、输出流这种叫法。
数据的传输形式又分为字节流和字符流:
-
字节流:读取和输出都是以一个字节为单位,适合二进制数据的传输【图片、音频等】。
-
字符流:读取和输出都是以一个字符为单位,也就是说每次读取n个字节(n取决于编码方式),适合文本数据的传输【.txt、.java、.html等文件】。相比于字节流多了编码解码的步骤,例如以UTF-8编码时(一个中文字符3字节),读取是3个字节为单位的读取,然后解码为字符,输出时,将中文字符编码,3个字节为单位的输出。
- 所以将字节流和字符流区分出来的关键是为了避免文本数据传输时字符的数据被分割而造成乱码问题
- 输入输出是相对于CPU而言的,硬件向CPU传数据—输入,CPU向硬件传数据—输出
字节流输入输出
输入
InputStream是一个抽象类,这里仅以其中一个实现类FileInputStream作为演示。
- 打开文件
InputStream input=new FileInputStream("test.txt");
//可使用try-with-rescources语法,防止忘记关闭文件
//可以使用这一语法的前提是继承了AutoCloseable接口。
- 读取
方法名 | 用法 |
---|---|
read() | 一次读取一个字节;读取成功则返回一个0~255的int值(代表这个字节的十进制表示),无字节可读取返回-1 |
read(byte[ ] arr) | arr相当于一个缓冲区, 一次性读取不超过arr.length个字节到arr里存放;返回读取成功字节数,无字节可读取返回-1 |
read(byte[ ] arr, int offset, int len) | 每次读取len个字节,且从arr的第offset个位置开始存放这len个字节;返回读取成功字节数,无字节可读取返回-1 |
- 关闭文件
如果使用了try-with-resources语法,在try执行完的时候就会自动执行close()方法,不用手动close()
inputStream.close();
输出
OutputStream同样是一个抽象类,这里用其中一个实现类FileOutputStream演示:
- 打开文件
OutputStream outputStream=new FileOutputStream("test.txt");
//但是这样构造每次打开时都会将文件内容清空再写,此时可以使用:
OutputStream outputStream=new FileOutputStream("test.txt", true);//追加写的形式
//可使用try-with-rescources语法
- 写入
方法名 | 用法 |
---|---|
write(int b) | 一次写入一个字节;这里的b应该是一个0~255范围的,代表一个字节的范围 |
write(byte[ ] arr) | 将字节数组里的所以字节一次性写入 |
write(byte[ ] arr, int offset, int len, int len) | 从字节数组的第offset个元素开始每次写入len个字节元素 |
- 关闭文件
outputStream.close();
//如果用了try-with-resources语法则不用调用这条语句手动关闭
字符流输入输出
输入
Reader是一个抽象类,这里仅以其中一个实现类FileReader作为演示:
- 打开文件
Reader reader=new FileReader("test.txt");
//可使用try-with-rescources语法
- 读取
方法名 | 用法 |
---|---|
read() | 一次读取一个字符;返回0~0xffff(两个字节大小)的int值(Unicode码点),无字符可读取返回-1 |
read(char[ ] arr) | 一次性读取最多arr.length个字符并存放在字符数组中;返回读取字符数,无字符可读取返回-1 |
read(CharBuffer[ ] arr | CharBuffer是对char的封装,最重要的是提供了字符缓冲区提高了读取效率;一次性读取最多arr.length个字符并存放在字符数组中;返回读取字符数,无字符可读取返回-1 |
read(char[ ] arr, int offset, int len) | 一次性读取len个字符,从arr的第offset个位置开始存储;返回读取字符数,无字符可读取返回-1 |
- 文件关闭
reader.close();
//如果使用了try-with-resources语法则不用手动关闭
输出
Writer也是一个抽象类,这里仅用其中一个实现类FileWriter演示:
- 打开文件
FileWriter writer=new FileWriter("test.txt");
//可使用try-with-resources语法
//同FileInputStream()一样,每次打开都会清空内容,所以创建对象时可设置为追加模式:
FileWriter writer=new FileWriter("test.txt",true);
- 写入
方法名 | 用法 |
---|---|
write(int c) | 传入的是一个Unicode码点(一个字符独占一个)的十进制数值 |
write(String s) | 传入一个字符串,将其写入文件 |
write(char[ ] arr) | 传入一个字符数组,并将所有元素写入文件 |
write(String s, int offset, int len) | 从字符串的第offset个字符开始写入len个字符文件(注意数组越界) |
write(char[ ] arr, int offset, int len) | 从字符数组的第offset个元素开始写入len个字符到文件(注意数组越界) |
- 文件关闭
writer.close();
练习代码供参考:练习代码
完。