1.文件的操作:
- 文件分为狭义上的文件和广义的文件。
- 狭义上的文件:存储在硬盘上的数据,以“文件”为单位进行组织。文件夹也叫做目录。
- 通过“路径”的概念来描述一个文件在电脑上的具体位置。路径分为绝对路径(每个 / 间隔的部分都是目录)和相对路径(需要有基准)。
- 相对路径中 ./表示当前目录(./qq/Bin/QQ.exe);使用 ../ 表示返回到上级目录。
- I(input)O(output),输入和输出的方向是以CPU/内存为中心。输入就是将外部设备(键盘)的数据放到内存里。
- File类;注意:有File对象不代表有真实存在该对象。File类的构造方法常用File(路径),这里的路径可以是绝对路径还可以是相对路径。一个file对象就是一个文件或目录。
File file = new File("..//helloworld.txt");//并不要求该文件真实存在
返回值类型 | 方法签名 | 说明 |
String | getName() | 返回File对象纯文件名称 |
boolean | isDirectory() | 判断是不是目录 |
boolean | isFile() | 判断是不是普通文件 |
boolean | createNewFile() | 创建文件,成功后返回true |
boolean | delete() | 删除该文件,成功后返回true |
void | deleteOnExit() | 进程退出时才会删除文件 |
boolean | mkdir() | 创建目录 |
boolean | mkdirs() | 创建多级目录 |
boolean | renameTo() | 重命名 |
2.文件内容的读写—数据流:
- 读操作:InputStream;从外部设备读取到内存上。
//InputStream是一个抽象类,不具体,不能实例化,所以需要用到FileInputStream
//下面这个过程就相当于打开文件!想要读写文件就需要打开文件~
InputStream inputStream = new FileInputStream("hello.txt");
返回值类型 | 方法签名 | 说明 |
int | read() | 读取一个字节的数据,返回-1代表读完了 |
int | read(byte[ ] b) | 读取b.length字节数据放到b中,返回读到的数量,-1代表已经读完了 |
int | read(byte[ ] b, int m, int n) | 读取n-m个字节到b中 |
void | close() | 关闭字节流 |
//1.读操作:无 public static void main(String[] args) throws IOException { InputStream inputStream = new FileInputStream("hello.txt"); while(true){ int ret = inputStream.read(); if(ret == -1){ break; } System.out.println(ret); } inputStream.close(); } //2.读操作:使用Scanner来读数据 public static void main(String[] args) throws IOException { InputStream inputStream = new FileInputStream("./hello.txt"); //scanner搭配inputStream使用,读操作 Scanner scanner = new Scanner(inputStream); while(scanner.hasNext()){ System.out.println(scanner.next()); } inputStream.close(); } //3.读操作:使用byte数组 public static void main(String[] args) throws IOException { try(InputStream inputStream = new FileInputStream("hello.txt")){ byte[] ret = new byte[1024]; int len = 0; while(true){ len = inputStream.read(ret); if(len == -1){ break; } for (int i = 0; i < len; i++) { System.out.println(ret[i]); } } } } //4.读操作:使用try和scanner public static void main(String[] args) throws IOException { try(InputStream inputStream = new FileInputStream("./hello.txt"); Scanner scanner = new Scanner(inputStream)){ while(scanner.hasNext()){ String ret = scanner.next(); System.out.println(ret); } } }
- 写:OutputStream;
//OutputStream是一个抽象类,不具体,不能实例化,所以需要用到FileOutputStream
//使用OutputStream写文件的时候,只要文件打开成功,就会把文件原来的内容清空
OutputStream outputStream = new FileOutrputStream("./hello.txt");
返回值类型 | 方法签名 | 说明 |
void | write(int b) | 写入一个字符将b这个字符数组中的数据全部写入 |
void | write(byte[ ] b) | 将b这个字符数组中的数据全部写入 |
int | write(byte[ ] b, int m, int n) | 将b这个字符数组中的数据从m开始写入 |
void | close() | 关闭字节流 |
void | flush() | 刷新缓冲区 |
//1.写操作 public static void main(String[] args) throws IOException { OutputStream outputStream = new FileOutputStream("./hello.txt"); //打开文件后,会先把文件内容清空 outputStream.write(97); outputStream.write(98); outputStream.write(99); outputStream.close(); } //2.写操作:使用PrintWriter来写操作 public static void main(String[] args) throws IOException { OutputStream outputStream = new FileOutputStream("./hello.txt"); PrintWriter writer = new PrintWriter(outputStream); writer.print(45); writer.print('c'); writer.println(); //一定要刷新缓冲区 outputStream.flush(); //一定要关闭文件,writer.close()!!! writer.close(); } //3.写操作:使用try和PrintWriter来写操作 public static void main(String[] args) throws IOException { try(OutputStream outputStream = new FileOutputStream("./hello.txt"); PrintWriter writer = new PrintWriter(outputStream)){ writer.println(); writer.print('s'); writer.flush(); } } //4.写操作:使用OutputStreamWriter和PrintWriter来写 public static void main(String[] args) throws IOException { try(OutputStream outputStream = new FileOutputStream("./hello.txt"); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream); PrintWriter printWriter = new PrintWriter(outputStreamWriter)){ printWriter.println(); printWriter.print(1); printWriter.print(12); printWriter.print(13); printWriter.flush(); } }
- 刷新缓冲区:OutputStream为了减少设备操作的次数,写数据时会将数据暂时写入缓冲区中,直到满足条件才写到内存上。因此为了保证数据不会遗留在缓冲区上,我们需要用到刷新缓存区flash()的操作来将数据刷到设备上。
- 文件内容操作后一定要将文件close,否则会造成文件资源泄露,类比于图书馆借书(一伙人直只借不还,图书馆的书不就越来越少了嘛~)。
为什么需要close文件???
1.每个进程都对应着PCB,PCB里面有一个字段,文件描述符表
2.同一个进程里面多个PCB可能同时使用一份文件描述符表
3.文件描述符表相当于一个数组,每次打开一个文件,都会在表里创建一个项
4.如果关闭则会把对应的项给释放掉
5.如果不关闭,意味着这个项一直占着位置,
6.如果持续打开文件且从来不关就会导致表项(数组里的元素)被耗尽
7.导致后续文件在打开文件就会打开失败
8.所以需要保证代码执行完关闭文件
3.文件操作练习:
1.扫描指定目录,并找到名称中包含指定字符的所有普通文件(不包含目录),并且后续询问用户是否要删除该文件
思路:
1.先让用户输入要扫描的路径和要查找的字
2.遍历目录,找到名字包含的的文件
3.询问用户是否删除
代码:
//扫描目录,找到包含指定字符的所有普通文件,找到后询问是否要删除 public class Demo { public static void main(String[] args) throws IOException { //1.让用户输入必要的信息 Scanner scanner = new Scanner(System.in); System.out.println("请输入要扫描的路径:"); File rootDir = new File(scanner.next()); if(!rootDir.isFile()){ System.out.println("输入的目录有错误!!!"); return; } System.out.println("请输入要查找的关键字:"); String toDelete = scanner.next(); //2.遍历目录 scanDir(rootDir,toDelete); } private static void scanDir(File rootDir, String toDelete) throws IOException { System.out.println("当前访问: "+rootDir.getCanonicalPath()); File[] files = rootDir.listFiles(); if(files == null){ //说明目录是个空的目录 return; } for (File f : files) { if(f.isDirectory()){ scanDir(f,toDelete); }else{ checkDelete(f,toDelete); } } } private static void checkDelete(File f, String toDelete) throws IOException { if(f.getName().contains(toDelete)){ System.out.println("该单词"+toDelete+" 被 "+f.getCanonicalPath()+"包含了,是否要删除?(Y/N)" ); Scanner scanner = new Scanner(System.in); String choice = scanner.next(); if(choice.equals("Y") || choice.equals("y")){ f.delete(); } } } }
2.将普通的文件复制一份
思路:
把第一个文件打开,将里面的内容逐个字节的读取出来,写入到第二个文件中
代码:
//普通文件的复制 public class Demo { public static void main(String[] args) throws IOException { //1.输入 Scanner scanner = new Scanner(System.in); System.out.println("请输入要复制的源文件:"); File srcFile = new File(scanner.next()); System.out.println("请输入目标文件:"); File destFile = new File(scanner.next()); if(!srcFile.isFile()){ System.out.println("输入的源文件有错误!!!"); return; } if(!destFile.getParentFile().isDirectory()){ System.out.println("输入的目标文件有误!!!"); return; } //2.打开目标文件,按照字节读取写入到目标文件中 try(InputStream inputStream = new FileInputStream(srcFile); OutputStream outputStream = new FileOutputStream(destFile)){ while(true){ int ret = inputStream.read(); if(ret == -1){ break; } outputStream.write(ret); } } } }
3.扫描指定目录,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录)
思路:
1.先让用户输入要扫描的路径和要查找的字
2.遍历目录,找到名字和内容都包含的文件
3.询问用户是否删除
代码:
//扫描文件,判断其中是否包含关键字 public class Demo { public static void main(String[] args) throws IOException { Scanner scanner = new Scanner(System.in); System.out.println("请输入要扫描的路径:"); File rootDir = new File(scanner.next()); if(!rootDir.isFile()){ System.out.println("输入的路径有问题!"); return; } System.out.println("请输入要搜索的关键字:"); String toFind = scanner.next(); //2.遍历 scanDir(rootDir,toFind); } private static void scanDir(File rootDir, String toFind) throws IOException { System.out.println("当前路径:"+rootDir.getCanonicalPath()); File[] files = rootDir.listFiles(); if(files == null){ return; } for(File f : files){ if(f.isDirectory()){ scanDir(f,toFind); }else{ checkDelete(f,toFind); } } } private static void checkDelete(File f, String toFind) throws IOException { //先检查文件名 if(f.getName().contains(toFind)){ System.out.println(f.getCanonicalPath() + "文件名中包含 " + toFind+" 是否删除(Y/N)"); } try(InputStream inputStream = new FileInputStream(f)){ StringBuilder sb = new StringBuilder(); Scanner scanner = new Scanner(inputStream); while(scanner.hasNextLine()){ sb.append(scanner.nextLine() + "\n"); } if(sb.indexOf(toFind) > -1){ System.out.println(f.getCanonicalPath() + "文件内容中包含 " + toFind+" 是否删除(Y/N)"); } } } }
如果对您有帮助的话,
不要忘记点赞+关注哦,蟹蟹
如果对您有帮助的话,
不要忘记点赞+关注哦,蟹蟹
如果对您有帮助的话,
不要忘记点赞+关注哦,蟹蟹