目录
1.认识文件
1.1文件的分类
1.2.目录的结构
2.Java中操作文件
操作文件
File类的方法:
创建文件 createNewFile()
delete删除文件
mkdir创建目录
mkdirs创建多级目录
list、listFiles
3.文件内容相关操作
3.1打开文件
3.2利用字节流读取文件
3.3写文件操作
4.针对字符流进行
4.1读操作:
4.2写操作
5.利用Scanner进行字符读取
6.文件操作案例
6.1案例1
6.2案例二
6.3案例三:
1.认识文件
我们平常所说的文件就是硬盘上存储的类似于.txt,压缩文件等。但是如果我们站在计算机的角度来看,文件就是一个广义的概念,不只是包含普通文件,还包括目录(文件夹),目录就被我们成为目录文件。
在操作系统中,还会用文件来描述一些其他的硬件设备或软件资源。比如网卡,这是一个硬件设备。但是操作系统就把网卡这样的硬件设备也给抽象成了一个文件。并且显示器/键盘这样的硬件设备也被操作系统视为文件。
1.1文件的分类
文件主要有两类:
1)文本文件:里面存储的是字符。
2)二进制文件:里面存储的是字节。
有的人可能会有疑问:字符不也是字节构成的吗?
是的,确实如此。文本文件本质上也是存字节的。
但是文本文件中,相邻的字节在一起正好能构成一个个的字符。
所以,我们所说的存储单位是 字符,其实意思就是:相邻的这些字节之间 是存在关联关系的,不是毫不相干的!
而二进制文件里面存储的字节,相互之间是完全没有关系。
判断一个文件是二进制文件还是文本文件,最简单的方法就是,利用记事本打开这个文件,如果是乱码就是二进制文件,如果不是乱码,一般就是文本文件。平常来说,像.txt、.c、.java都属于文本文件,像.doc、.ppt、.exe、.zip、.class都属于二进制文件。
1.2.目录的结构
计算机里,保存管理文件,是通过 操作系统 中的“文件系统” 这样的模块来负责的。
在文件系统中,一般是通过“树形”结构来组织硬盘上的目录和文件的。
在操作系统中,我们可以通过路径这样的概念,来描述一个具体文件或目录的位置。这里我们有两种路径描述风格:
1)绝对路径:以盘名为开头的,如C、D、E
2)相对路径:以 . 或者 … 开头的文件路径。其中 . 表示当前路径, … 表示当前路径的父目录(上级路径)。谈到相对路径,必须要有一个基准目录。对于路径就是从基准目录出发,按照一个什么样的路径找到的对应文件。
简单来说相对路径就是我们身处哪个地方,然后以一种什么样的方式来找到目的地。
2.Java中操作文件
Java中操作文件主要包含两类操作,一个是文件系统相关的操作,一个是文件内容相关的操作。
其中文件系统相关的操作指的是文件系统相关的操作,即通过文件资源管理器完成的一些操作。
这下操作包括:1、列出目录中有哪些文件
2、创建文件(直接右键点击菜单创建,就可以创建了)
3、创建 目录/文件夹
4、删除文件
5、重命名文件
…在Java中提供了一个File类,我们可以通过这个类完成上述操作。
File的概述:
属性:
构造方法:
File 的构造方法,能够传入一个路径,来指定一个文件。
这个路径可以是绝对路径,也可以是相对路径。
方法:
操作文件
但是在上述代码中,基准路径是啥,我们看不出来。因此 我们需要在java中的运行中找一下:
File类的方法:
public class Test1 {
public static void main(String[] args) throws IOException {
File file = new File("d:/test.txt");
System.out.println(file.getParent());// 获取到文件的父目录文件路径
System.out.println(file.getName());// 获取到文件名
System.out.println(file.getPath());// 获取到文件路径(构造 file 的时候指定的路径)
System.out.println(file.getAbsolutePath());// 获取到绝对路径
System.out.println(file.getCanonicalPath());// 获取到绝对路径.[需要处理异常]
System.out.println("====================");
File file1 = new File("./test.txt");
System.out.println(file1.getParent());// 获取到文件的父目录文件路径
System.out.println(file1.getName());// 获取到文件名
System.out.println(file1.getPath());// 获取到文件路径(构造 file 的时候指定的路径)
System.out.println(file1.getAbsolutePath());// 获取到绝对路径
System.out.println(file1.getCanonicalPath());// 获取到绝对路径.[需要处理异常]
}
}
import java.io.File;
public class TestDemo2 {
public static void main(String[] args) {
File file = new File("d:/test.txt");
System.out.println(file.exists());//判断文件是否真实存在
System.out.println(file.isDirectory());//判断文件是否是一个目录
System.out.println(file.isFile());//判断文件是否是一个普通文件
System.out.println("==========");
File file1 = new File("./test.txt");
System.out.println(file1.exists());//判断文件是否真实存在
System.out.println(file1.isDirectory());//判断文件是否是一个目录
System.out.println(file1.isFile());//判断文件是否是一个普通文件
}
}
创建文件 createNewFile()
delete删除文件
import java.io.File;
public class TestDemo4 {
public static void main(String[] args) {
File file = new File("./test.txt");
System.out.println(file.exists());
file.delete();// 删除文件
System.out.println(file.exists());
}
}
mkdir创建目录
public class TestDemo5 {
public static void main(String[] args) {
//在当前项目底下创建一个 aaa 目录
File file = new File("./aaa");
System.out.println(file.isDirectory());
file.mkdir();// mkdir 方法 只能创建一级目录
System.out.println(file.isDirectory());
}
}
public class TestDemo5 {
public static void main(String[] args) {
//在当前项目底下创建一个 aaa 目录
File file = new File("./aaa");
System.out.println(file.isDirectory());
file.mkdir();// mkdir 方法 只能创建一级目录
System.out.println(file.isDirectory());
}
}
mkdirs创建多级目录
public class TestDemo5 {
public static void main(String[] args) {
//在当前项目底下创建一个 aaa 目录
File file = new File("./aaa/bbb/ccc");
System.out.println(file.isDirectory());
file.mkdirs();
System.out.println(file.isDirectory());
}
}
list、listFiles
public class TestDemo6 {
public static void main(String[] args) {
File file = new File("./aaa");
System.out.println(file.list());
// 这个操作就是把 aaa目录里面的内容列举出来
System.out.println(Arrays.toString(file.list()));
}
}
listFile
listFiles 方法 和 list 方法差不多,只是返回的类型不同。
listFiles 返回是 File 类型的数组。
list 返回的是 字符串数组。不然我们也不可能通过数组的方法,来输出结果。
renameTo
3.文件内容相关操作
3.1打开文件
主要分为4个步骤:
1)打开文件
2)读取文件
3)写文件
4)关闭文件
3.2利用字节流读取文件
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class Test3 {
public static void main(String[] args) {
//FileInputStream的构造方法需要制定打开文件的路径
//路径可以是绝对路径,相对路径,还可以是File对象
try {
//1.创建对象,同时也是在打开文件
InputStream inputStream = new FileInputStream("d:/test.txt");
int b = inputStream.read();//这里会爆出异常,是因为我们读取文件的时候,可能磁盘会被突然损坏,这样就会读取失败
} catch (IOException e) {
e.printStackTrace();
}
}
}
继续读文件
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class Test3 {
public static void main(String[] args) throws IOException {
//FileInputStream的构造方法需要制定打开文件的路径
//路径可以是绝对路径,相对路径,还可以是File对象
InputStream inputStream = null;
try {
//1.创建对象,同时也是在打开文件
inputStream = new FileInputStream("d:/test.txt");
//2.尝试一个一个字节的读,直至把整个文件读完
while (true) {
int b = inputStream.read();//这里会爆出异常,是因为我们读取文件的时候,可能磁
//盘会被突然损坏,这样就会读取失败
if (b == -1) {
//读到文件末尾就返回
break;
}
System.out.println(b);
}
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}finally {
//3.读完之后记得关闭文件,释放资源
inputStream.close();
}
}
}
可是这个代码太复杂,我们换一种写法:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class Test3 {
public static void main(String[] args) throws IOException {
//FileInputStream的构造方法需要制定打开文件的路径
//路径可以是绝对路径,相对路径,还可以是File对象
try (InputStream inputStream = new FileInputStream("d:/test.txt")) {
//1.创建对象,同时也是在打开文件
//2.尝试一个一个字节的读,直至把整个文件读完
while (true) {
int b = inputStream.read();//这里会爆出异常,是因为我们读取文件的时候,可能磁盘会被突然损坏,这样就会读取失败
if (b == -1) {
//读到文件末尾就返回
break;
}
System.out.println(b);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
接下来我们一次去读取多个字节:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class Test4 {
public static void main(String[] args) {
try(InputStream inputStream = new FileInputStream("d:/test.txt")){
while (true){
//将从文件中读取的数据存入buffer数组中,read方法是返回读取到的数据个数
byte[] buffer = new byte[1024];//缓冲数组
int len = inputStream.read(buffer);
if(len == -1){
break;
}
//输出读到的文件
for (int i = 0; i < len; i++) {
System.out.println(buffer[i]);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.3写文件操作
一个一个写:
多个多个写:
4.针对字符流进行
4.1读操作:
换一种输出方式:
4.2写操作
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class Test7 {
public static void main(String[] args) {
try(Writer writer = new FileWriter("d:/test.txt",true)){
writer.write("qwer");
} catch (IOException e) {
e.printStackTrace();
}
}
}
5.利用Scanner进行字符读取
利用我们之前熟悉的Scanner类来进行读取:
import java.io.*;
import java.util.*;
// 需要先在项目目录下准备好一个 hello.txt 的文件,里面填充 "你好中国" 的内容
public class Main {
public static void main(String[] args) throws IOException {
try (InputStream is = new FileInputStream("hello.txt")) {
try (Scanner scanner = new Scanner(is, "UTF-8")) {
while (scanner.hasNext()) {
String s = scanner.next();
System.out.print(s);
}
}
}
}
}
6.文件操作案例
6.1案例1
扫描指定目录,并找到名称中包含指定字符的所有普通文件(不包含目录),并且后续询问用户是否要删除该文件
意思就是:
用户输入一个目录
再输入一个要删除的文件名
找到名称中包含指定字符的所有普通文件
询问用户是否要删除该文件
public class Test8 {
public static void main(String[] args) {
//1.先输入要扫描的目录,以及要删除的文件名
Scanner scanner = new Scanner(System.in);
System.out.println("请输入要扫描的路径");
String rootDirectoryPath = scanner.next();
System.out.println("请输入要删除的文件夹");
String DeleteFileName = scanner.next();
//以rootDirectoryPath的路径,创建一个File对象
File rootDirectory = new File(rootDirectoryPath);
if(! rootDirectory.isDirectory()){
//判断输入路径是否存在
//如果不存在,执行下面内容
System.out.println("输入的扫描路径有误");
return;
}
//2.遍历目录,把指定目录中的所有文件和子目录都遍历一遍
//从而要找删除的文件
//通过scannerDirectory方法来实现递归遍历
scannerDirectory(rootDirectory,DeleteFileName);
}
private static void scannerDirectory(File rootDirectory,String DeleteFileName){
//1.先列出rootDirectory中都有哪些内容
File[] files = rootDirectory.listFiles();
if(files == null){
//rootDirectory是一个空目录,即files就是一个空数组
return;
}
//2.遍历当前列出的这些内容,如果是普通文件,就检测是否是要删除的文件
//只要文件名包含了关键字,即可删除
//如果是目录,就递归进行遍历
for(File f : files){
//判断是否是普通文件
if(f.isFile()){
if(f.getName().contains(DeleteFileName)){
//即可热进行删除
deleteFile(f);
}//判断是否是目录,是就递归遍历
}else if(f.isDirectory()){
scannerDirectory(f, DeleteFileName);
}
}
}
private static void deleteFile(File f){
try {
System.out.println("确认要删除" + f.getCanonicalPath() + "?" +"(Yes or No)");
Scanner scanner = new Scanner(System.in);
String choice = scanner.next();
if(choice.equals("Yes") || choice.equals("No")){
f.delete();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
6.2案例二
进行普通文件的复制
我们需要让用户指定两个文件路径。
一个是原路径(被复制的文件)
一个是目标路径(复制之后生成的文件)
从哪里复制到哪里,从哪里来到哪来去。
我们需要描述清楚 起点 和 终点。
然后,我们就可以在这个基础上进行具体复制操作
我们要做的事很简单。
打开源路径文件,读取里面的内容,并写入到目标文件中,
import java.io.*;
import java.util.Scanner;
public class TestDemo13 {
public static void main(String[] args) {
//1、输入两个路径
Scanner sc = new Scanner(System.in);
System.out.println("请输入要拷贝的源路径:");
String source = sc.next();
System.out.println("请输入要拷贝的目标路径:");
String destination = sc.next();
File file = new File(source);
if(!file.isFile()){
System.out.println("输入的源路径不正确!");
return;
}
// 此处不太需要检查目标文件是否存在,OutputStream 写文件的时候,能够自动创建不存在的文件。
//2、读取源文件,拷贝到目标路径
try(InputStream inputStream = new FileInputStream(source)){
try(OutputStream outputStream= new FileOutputStream(destination)){
// 把 inputStream 的数据 读出来,写到 outputStream
byte[] buffer= new byte[1024];
while(true){
// 从 source 文件读取到的元素个数
int len = inputStream.read(buffer);
if(len == -1){
// 文件读完了
break;
}
// 写入的时候,不能把整个buffer 都写进入。
// 毕竟 buffer 可能只有一部分才是有效数据。【数组可能没存满】
outputStream.write(buffer,0,len);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
6.3案例三:
扫描指定目录,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录)
进行文件内容的查找
1、输入一个路径
2、再输入一个要查找文件的 关键字
3、递归的遍历文件,找到看哪个文件里的内容包含了那些关键词,就把对应的文件路径打印出来。
import java.io.*;
import java.util.Scanner;
public class TestDemo14 {
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
System.out.println("输入要扫描的路径:");
String rootDirectoryPath = sc.next();
System.out.println("输入要查询的文件名关键字:");
String keyword = sc.next();
File file = new File(rootDirectoryPath);
if(!file.isDirectory()){
// 此路径不存在
System.out.println("输入的扫描路径错误!");
return;
}
//3、进行递归遍历
scannerDirectory(file,keyword);
}
private static void scannerDirectory(File file,String keyword) throws IOException {
// 1、先列出 file 中 有哪些内容
File[] files = file.listFiles();
if(files == null){
return;
}
for (File f: files) {
if(f.isFile()){
// 针对普通文件的内容,进行判断,是否满足查询条件【文件内容 是否包含 关键字keyword】
if(containsKeyword(f,keyword)){
System.out.println(f.getCanonicalPath());
}
}else if(f.isDirectory()){
// 针对目录进行递归
scannerDirectory(f,keyword);
}
}
}
private static boolean containsKeyword(File f,String keyword){
//把 f 中的内容 都读出来,进行遍历,放到一个 StringBuilder 中
StringBuilder stringBuilder = new StringBuilder();
try (Reader reader = new FileReader(f)){
char[] buffer = new char[1024];
while(true){
int len = reader.read(buffer);
if(len == -1){
break;
}
// 把这一段读到的结果,放到 StringBuilder中
stringBuilder.append(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}
// indexOf 返回的是子串(keyword)的下标,如果 word 在 stringBuilder中不存在,则返回 -1。
return stringBuilder.indexOf(keyword) != -1;
}
}



