文件
1.狭义上的文件:
硬盘上保存的数据,都是“文件”来组织的,本质上都是二进制或是字符组织的数组,被打包成一个文件存在硬盘上。常见的文件有图片,文本,可执行文件,音频,视频…文件夹也是一种特殊的文件,也叫目录通常所说的文件都是存储在硬盘上面的,硬盘的特点:1硬盘容量大,内存容量小。2.硬盘读写速度慢,内存读写速度快。3.硬盘造价低,内存成本比较高。4.硬盘上的数据断电不丢失,内存中的数据断电丢失。
2..广义上的文件:
操作系统的主要功能就是对计算机资源进行统一管理与分配。对于Linux来讲,所有的计算设备(网卡、键盘、打印机…)都会被描述(抽象)成文件。当一个进程启动后去申请计算机资源时,系统会把他所有用到的资源以文件的形式分配给进程,并加入到对应的文件描述符表中。
3.树形结构和目录
通过 tree /F
在命令行查看指定目录的树形结构。
4.绝对路径
从根目录开始一直到目标程序的表示方式。
5.相对路径
从当前目录开始表示目标程序路径的方式。如果要通过相对路径的方式访问到目标文件,那么就得先确认自己当前的工作目录。对于ideal来说,起始工作目录就是工程的根目录。
⚠️注意
平时使用的时候可以使用绝对,工作和项目中尽量使用相对路径。
Java操作文件
操作系统的一个重要功能就是对文件的管理,每个操作系统都有自己的一套系统API调用,Java作为一个跨平台的语言,JVM针对不同的操作系统做了一层封装,我们只需要使用JDK提供的关于文件操作的API就可以完成不同系统上的文件操作。
File类
用来操作文件的类,位于java.io包下。I:input,O: output。输入输出以内存为参照物的。输入指的是从外部输入到内存,输出指的是把内存的数据输出外部(磁盘)。
属性
修饰符及类型 | 属性 | 说明 |
---|---|---|
static String | pathSeparator | 依赖于系统的路径分隔符,String 类型的表示 |
static char | pathSeparator | 依赖于系统的路径分隔符,char 类型的表示 |
构造方法
签名 | 说明 |
---|---|
File(File parent, String child) | 根据父目录 + 孩子文件路径,创建一个新的 File 实例 |
File(String pathname) | 根据文件路径创建一个新的 File 实例,路径可以是绝对路径或者相对路径 |
File(String parent, String child) | 根据父目录 + 孩子文件路径,创建一个新的 File 实例,父目录用路径表示 |
public class Demo01_File {
public static void main(String[] args) {
//通过指定文件路径来创建一个File对象
File file = new File("D:\\test\\hello.txt");
System.out.println(file);
File file1 = new File("D:/test/hello.txt");
System.out.println(file1);
//这只是java层面的一个对象,并不一定必须在系统中真实存在
File file2 = new File("D:/test/test.txt");
System.out.println(file2);
}
}
注意斜杠与反斜杠的区别,反斜杠需要转义。
常用方法
修饰符及返回值类型 | 方法签名 | 说明 |
---|---|---|
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() | 判断用户是否对文件有可写权限 |
public class Demo02_FileUsae {
public static void main(String[] args) throws IOException {
//指定绝对路径来创建一个File对象
File file = new File("D:/test/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());
// 是否存在
System.out.println(file.exists());
// 是不是一个目录
System.out.println(file.isDirectory());
// 是不是一个文件
System.out.println(file.isFile());
//
// // 创建文件
// boolean result1 = file.createNewFile();
// if (result1) {
// System.out.println("创建成功");
// } else {
// System.out.println("创建失败");
// }
//
// // 删除
// boolean result2 = file.delete();
// if (result2) {
// System.out.println("删除成功");
// } else {
// System.out.println("删除失败");
// }
// // 指定一个目录的路径
// File file = new File("d:/test");
// // 获取目录下的文件和子目录
// String[] list = file.list();
// System.out.println(Arrays.toString(list));
//
// // 获取目录下的文件对象数组
// File[] files = file.listFiles();
// System.out.println(Arrays.toString(files));
// // 指定要创建的目录
// File file = new File("D:/test/java");
// // 创建单个目录
// boolean result = file.mkdir();
// if (result) {
// System.out.println("创建成功");
// } else {
// System.out.println("创建失败");
// }
// // 指定要创建的目录
// File file = new File("D:/test/java/a/b/c");
// // 创建单个目录
// boolean result = file.mkdirs();
// if (result) {
// System.out.println("创建成功");
// } else {
// System.out.println("创建失败");
// }
// // 定义源文件
// File sourceFile = new File("D:/test/hello.txt");
// // 定义目标文件
// File destFile = new File("D:/test/haha.txt");
// // 重命名
// boolean result = sourceFile.renameTo(destFile);
// if (result) {
// System.out.println("修改成功");
// } else {
// System.out.println("修改失败");
// }
//
// File file = new File("D:/test/haha.txt");
// // 是否可写
// System.out.println(file.canWrite());
// // 是否可读
// System.out.println(file.canRead());
// //指定相对路径来创建一个File对象
// 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());
// // 是否存在
// System.out.println(file.exists());
// // 是不是一个目录
// System.out.println(file.isDirectory());
// // 是不是一个文件
// System.out.println(file.isFile());
}
}
文件内容的读写-数据流
字节流(处理二进制文件)
InputStream和FileInputStream
🟢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 只是一个抽象类,要使用还需要具体的实现类。我们现在只关心从文件中读取,所以使用 FileInputStream类。
🟢FileInputStream类的构造方法
方法 | 说明 |
---|---|
FileInputStream(File file) | 利用 File 构造文件输入流 |
FileInputStream(String name) | 利用文件路径构造文件输入流 |
示例:读取文件
public class Demo03_InputStream_Read01 {
public static void main(String[] args) throws IOException {
// 创建一个文件对象
File file = new File("d:/test/haha.txt");
// 创建一个输入流
InputStream inputStream = new FileInputStream(file);
// 读取文件内容
while (true) {
int read = inputStream.read();
// 是否读完
if (read == -1) {
break;
}
System.out.println(read);
}
// 关闭
inputStream.close();
}
}
示例:用一个数组用来保存读取到的数据,遍历数组即可读取到数据。
public class Demo04_InputStream_Read02 {
public static void main(String[] args) throws IOException {
// 创建一个文件对象
File file = new File("d:/test/haha.txt");
// 创建一个输入流
InputStream inputStream = new FileInputStream(file);
// 定义一个数组用来保存读取到的数据
byte[] bytes = new byte[1024];
// 读取文件内容
while (true) {
// 读到的数据会被填充到bytes数据中,返回读取数据的长度
int len = inputStream.read(bytes);
// 判断是否读完
if (len == -1) {
break;
}
// 打印读到的内容
for (int i = 0; i < len; i++) {
System.out.println(bytes[i]);
}
}
// 关闭
inputStream.close();
}
}
在这个示例中,传入read()方法的是一个空数组,读文件时,读数组长度个字节,并返回读取到的字节数供调用方做判断。
打开一个文件相当于把文件放入文件描述符表中,本质上是一个数组。用完一定要关闭,如果不关闭,文件描述符表就会被填满,导致以后可能无法再打开文件。
OutputStream和FileOutputStream
OutputStream和FileOutputStream分别作为字节流中输出流的抽象类和实现类。
🟢OutputStream的方法
修饰符及返回值类型 | 方法 | 说明 |
---|---|---|
viod | write(int b) | 将数据写入指定的文件 |
viod | write(byte[] b) | 将 b 这个字符数组中的数据全部写入 os 中 |
int | write(byte[] b, int off,int len) | 将 b 这个字符数组中从 off 开始的数据写入 os 中,一共写 len 个 |
viod | close() | 关闭字节流 |
viod | flush() | 重要:我们知道 I/O 的速度是很慢的,所以,大多的 OutputStream 为了减少设备操作的次数,在写数据的时候都会将数据先暂时写入内存的一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写入设备中,这个区域一般称为缓冲区。但造成一个结果,就是我们写的数据,很可能会遗留一部分在缓冲区中。需要在最后或者合适的位置,调用 flush(刷新)操作,将数据刷到设备中。 |
public class Demo05_OutputStream {
public static void main(String[] args) throws IOException {
// 先创建一个File对象
File file = new File("d:/test/haha.txt");
// 根据File对象创建一个输出流
FileOutputStream outputStream = new FileOutputStream(file);
// 向文件中写入内容
outputStream.write(100);
outputStream.write(101);
outputStream.write(102);
// 刷新缓冲区
outputStream.flush();
// 关闭流
outputStream.close();
}
}
调用write()方法,就表示通过输出流把内容写到指定的文件中。
缓冲区本身是内存中的一片区域,写的文件内容一般是先写到缓冲区中,缓冲区的内容什么时候写到文件中是由操作系统决定的。如果缓冲区的内容还没写满就要强制写入文件时,可以使用flush()方法。
在完成写操作之后,建议强制调用flush()方法刷新缓冲区,确保文件内容被立即写入。
用输出流的方式去写文件内容,会把之前的内容全部覆盖掉。
字符流(处理文本文件)
Reader和FileReader
Reader和FileReader分别是字符流中输入流的抽象类和实现类。
public class Demo06_FileReader {
public static void main(String[] args) throws IOException {
// 创建一个File对象
File file = new File("d:/test/haha.txt");
// 根据File对象创建一个Reader(面向字符的输入流)
FileReader reader = new FileReader(file);
// 循环读取
while (true) {
// 一次读一个字符
int read = reader.read();
if (read == -1) {
break;
}
// 打印
System.out.println((char) read);
}
// 关闭流
reader.close();
}
}
read()方法每次只读一个字符。
Writer和FileWriter
Writer和FileWriter分别是字符流中输出流的抽象类和实现类。
public class Demo07_FileWriter {
public static void main(String[] args) throws IOException {
// 创建一个File对象
File file = new File("d:/test/haha.txt");
// 根据文件对象创建一个字符输出流
FileWriter writer = new FileWriter(file);
// 写入内容
writer.write("你好世界\n");
writer.write("hello world");
// 强制刷新缓冲区
writer.flush();
// 关闭流
writer.close();
}
}
write()方法每次写入一个字符串,写入时不会自动换行,需要换行时要手动添加换行符。
其他方法
Scanner(通过输入流读)
public class Demo08_Scanner {
public static void main(String[] args) throws IOException {
// 创建一个输入流
FileInputStream inputStream = new FileInputStream("d:/test/hello.txt");
// 根据创建输入流创建Scanner对象
Scanner scanner = new Scanner(inputStream, "UTF-8");
// 循环读取内容
while (scanner.hasNextLine()) {
String next = scanner.nextLine();
System.out.println(next);
}
scanner.close();
inputStream.close();
}
}
读数据时,调用nextLine()方法读取一行。
PrintWriter(通过输出流写)
public class Demo09_PrintWiter {
public static void main(String[] args) throws FileNotFoundException {
// 创建一个输出流
FileOutputStream outputStream = new FileOutputStream("d:/test/hello.txt");
// 根据输出流,创建一个PrintWriter
PrintWriter printWriter = new PrintWriter(outputStream);
// 写入文件
printWriter.println("你好世界!!!");
printWriter.println("hello world.");
printWriter.println("我是用PrintWriter写入的内容");
// 强制刷新缓冲区
printWriter.flush();
// 关闭流
printWriter.close();
}
}
写入字符串时,调用 println()方法会自动换行。
练习
1.扫描指定目录,并找到名称中包含指定字符的所有普通文件(不包含目录),并且后续询问用户是否要删除该文件。
1.用户输入一个路径;
2.检查路径是否有效;
3.用户输入目标字符;
4.获取路径下的文件和目录;
5.如果是目录,递归;
6.如果是文件检查文件名是否包含要用户输入的字符。
public class Ex01 {
public static void main(String[] args) throws IOException {
// 1. 接收用户输入的扫描路径
System.out.println("请输入要扫描的路径(绝对路径):");
Scanner scanner = new Scanner(System.in);
String rootPath = scanner.next();
// 2. 判断路径是否有效
File root = new File(rootPath);
// 2.1 路径是否存在
if (!root.exists()) {
System.out.println("路径不存在");
return;
}
// 2.2 判断File是不是一个目录
if (!root.isDirectory()) {
System.out.println("指定的路径不是一个有效目录");
return;
}
// 3. 接收关键字
System.out.println("请输入关键字");
String key = scanner.next();
if (key == null || "".equals(key)) {
System.out.println("关键字不能为为");
return;
}
// 4. 扫描目录下的所有文件
scan(root, key);
}
private static void scan(File root, String key) throws IOException {
// 1. 先获取root下的所有文件,包括目录
File[] files = root.listFiles();
// 递归的终止条件
if (files == null || files.length == 0) {
return;
}
// 遍历数组中的每个文件
for (int i = 0; i < files.length; i++) {
// 取出每一个文件
File tempFile = files[i];
// 判断是文件还是目录
if (tempFile.isFile()) {
// 如果是文件,判断文件名中是否包含关键字
String fileName = tempFile.getName();
// 如果在文件名中找到关键字
if (fileName.contains(key)) {
System.out.println("找到文件:" + tempFile.getCanonicalPath() + ", 是否删除(Y/N)");
// 接收用户的输入,根据输入判断是否删除
Scanner scanner = new Scanner(System.in);
String order = scanner.next();
// 删除操作
if (order.equalsIgnoreCase("y")) {
tempFile.delete();
System.out.println(tempFile.getCanonicalPath() + " 删除成功.");
}
}
} else {
// 如果是目录则递归
scan(tempFile, key);
}
}
}
}
2.对普通文件进行复制
1.用户输入源文件的路径;
2.检查源文件是否存在,并且是一个文件;
3.用户输入目标文件的路径;
4.检查目标文件是否存在,并校验目录或文件;
5.完成复制。
public class Ex02 {
public static void main(String[] args) {
// 1 . 接收用户输入的源文件路径
System.out.println("请输入源文件路径(绝对路径):");
Scanner scanner = new Scanner(System.in);
String sourcePath = scanner.next();
// 2. 判断源文件路径是否有效
File sourceFile = new File(sourcePath);
// 2.1 文件是否存在
if (!sourceFile.exists()) {
System.out.println("源文件不存在");
return;
}
// 2.2 判断是不是一个文件
if (!sourceFile.isFile()) {
System.out.println("源文件不是一个有效的文件");
return;
}
// 3. 接收用户输入的目标文件路径
System.out.println("请输入目标文件路径(绝对路径)");
String destPath = scanner.next();
File destFile = new File(destPath);
// 3.1 判断目标文件是否存在
if (destFile.exists()) {
System.out.println("目标文件已存在");
return;
}
// 3.2 判断目标文件的父目录是否存在
if (!destFile.getParentFile().exists()) {
System.out.println("目标文件的父目录不存在");
return;
}
// 循环读取源文件的内容并写到目标文件中
try (FileInputStream inputStream = new FileInputStream(sourceFile);
FileOutputStream outputStream = new FileOutputStream(destFile)) {
// 定义一个byte数组用来做为输出型参数,保存每次读到的文件内容
byte [] bytes = new byte[1024];
// 循环读取内容
while (true) {
int len = inputStream.read(bytes);
if (len == -1) {
break;
}
// 写义目标文件
outputStream.write(bytes);
// 强制刷新缓冲区
outputStream.flush();
}
System.out.println("复制成功");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
由于InputStream和OutputStream实现了Closeable类,所以可以在try()中完成声明,当代码退出try的代码块时,会自动调用close()方法。
文章来源:https://www.toymoban.com/news/detail-769613.html
继续加油~
文章来源地址https://www.toymoban.com/news/detail-769613.html
到了这里,关于【Java】文件的操作与输入输出流的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!