目录
系统中:“一切皆文件”。普通的文件是保存在硬盘(持久化存储的I/O设备)上的文件
元信息:文件的相 关属性(文件名、文件类型、文件大小等)
文件分类:文本文件(存储字符)、二进制文件(字节)
文件(剪切粘贴):高效,只需修改文件属性中的地址即可
文件(复制粘贴):低效,先读文件内容,再拷贝一份写入磁盘,开销大
Java 中通过 java.io.File 类来对一个文件(包括目录)进行抽象的描述。
File file = new File("d:/test.txt"); //给定地址下 创建一个文件
注意!!!有 File 对象,并不代表真实存在该文件。
- import java.io.File;
- import java.io.IOException;
-
- public class fileDemo {
- public static void main(String[] args) throws IOException {
- File file = new File("d:/test.txt"); //给定地址下 创建一个文件
- System.out.println(file.getName()); //获取文件名
- System.out.println(file.getParent()); //获取父目录
- System.out.println(file.getAbsoluteFile()); //获取绝对路径
- System.out.println(file.getCanonicalFile()); //相对路径
-
- System.out.println(file.exists()); //文件是否存在
- System.out.println(file.isFile()); //是否是一个普通文件
- System.out.println(file.isDirectory()); //是否是目录
-
-
- File file1 = new File("./aaa"); // 创建目录
- System.out.println(Arrays.toString(file1.list())); //列出目录下的文件
- System.out.println(Arrays.toString(file.listFiles()));
- }
- }
抽象类可针对普通文件、特殊文件(网卡、socket)进行读写;实际使用中都是使用这四个类的子类(FileInputStream、FileOutputStream、FileReader、FileWriter),子类只可对普通文件进行读写
abstract 抽象类,不能实例化
抽象方法(不需要实现)必须在抽象类里,使用时需创建子类,来重写这个方法
“流”stream对象
(1)读文件
- public static void main0(String[] args) {
- InputStream inputStream = null;
- try {
- inputStream = new FileInputStream("d:/test.txt");
- while (true) {
- int b = inputStream.read(); //一次读一个字节(一个字节的范围:-128,127)
- if (b == -1) { //读到了文件末尾
- break;
- }
- System.out.println(b); //若为字母则输出字母对应的ASCII值
- }
- } catch (IOException e) { //读操作可能触发的异常
- e.printStackTrace();
- } finally {
- try { //读完及时关闭文件,释放资源
- inputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-
- //=================代码改进:读一个字节===================//
- public static void main(String[] args) { // 此代码try会自动调用close
- try (InputStream inputStream = new FileInputStream("d:/test.txt")) {
- while (true) {
- int b = inputStream.read();
- if (b == -1) {
- break;
- }
- System.out.println(b);
- }
- }catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- //=================代码改进:读取多个字节===================//
- public static void main(String[] args) { // 此代码try会自动调用close
- try (InputStream inputStream = new FileInputStream("d:/test.txt")) {
- while (true) {
- byte[] buffer = new byte[1024]; //把读取的数据放到buffer数组中,以此来指代返回结果
- int len = inputStream.read(buffer); //读取多个字节
- if (len == -1) {
- break;
- }
- for (int i = 0; i < len; i++) {
- System.out.println(buffer[i]);
- }
- }
- }catch (IOException e) {
- e.printStackTrace();
- }
- }
(2)写文件:
每次写文件都会清空原有文件,从起始位置往后写。OutputStream 同样只是一个抽象类,要使用还需要具体的实现类。所以使用 FileOutputStream
I / O 速度很慢,所以,大多的 OutputStream 为了减少设备操作的次数,在写数据的时候都会将数据先暂时写入内存的一个指定区域buffer里,直到该区域满了或者其他指定条件时才真正将数据写入设备中,这个区域一般称为缓冲区。但造成一个结果,就是写的数据,很可能会遗留一部分在缓冲区中。需要在最后或者合适的位置,调用 flush(刷新)操作,将数据刷到设备中
- //=========================代码改进:写文件=====================//
- public static void main(String[] args) { // 此代码try会自动调用close
- try (OutputStream outputStream = new FileOutputStream("d:/test.txt")) {
- while (true) {
- byte[] buffer = new byte[1024]; //把读取的数据放到buffer数组中,以此来指代返回结果
- outputStream.write(buffer); //读取多个字节
- }
- }catch (IOException e) {
- e.printStackTrace();
- }
- }
读操作:
- public class Demo1 {
- public static void main(String[] args) {
- try(Reader reader =new FileReader("d:/test.txt")) {
- while (true) {
- char[] chars = new char[1024];
- int len = reader.read();
- if (len == -1) {
- break;
- }
- // for (int i = 0; i < len; i++) {
- // System.out.println(chars[i]);
- // }
- String str = new String(chars,0,len);
- System.out.println(str);
- }
- }catch(IOException e) {
- e.printStackTrace();
- }
- }
- }
写操作:
- public static void main(String[] args) {
- try(Writer writer = new FileWriter("d:/test.txt")) {
- writer.write("asdf");
- }catch (IOException e) {
- e.printStackTrace();
- }
- }
扫描指定目录,并找到名称中包含指定字符的所有普通文件(不包含目录),并且后续询问用户是否要删除该文件
- import java.io.File;
- import java.io.IOException;
- import java.util.Scanner;
-
- public class testDemo {
- public static void main(String[] args) {
- //1.输入要扫描的目录,以及删除的文件名
- Scanner in = new Scanner(System.in);
- System.out.println("请输入扫描路径");
- String scanRootPath = in.nextLine();
- System.out.println("请输入文件名");
- String toDelName = in.nextLine();
- File rootDir = new File(scanRootPath); //创建一个目录
- if (!rootDir.isDirectory()) { //判断是不是文件夹,若不是文件夹,退出
- System.out.println("输入的扫描路径有误,直接退出");
- return;
- }
- // 二叉树的遍历(先序,中序,后序,层序)
- scanDir(rootDir,toDelName); // 遍历指定目录的所有文件和子目录,找到需要删除的文件(可通过遍历实现递归操作并删除)
- }
-
- private static void scanDir(File rootDir, String toDelName) {
- File[] files = rootDir.listFiles(); //先列出rootDir中都有的内容
- if (files == null) {
- return;
- }
- for (File f : files) {
- if (f.isFile()) { //普通文件的情况
- if (f.getName().contains(toDelName)) {
- deleteFile(f); //删除文件
- }
- } else if (f.isDirectory()) { //目录进行递归
- scanDir(f,toDelName); //递归操作,继续遍历
- }
- }
- }
-
- private static void deleteFile(File f) {
- try {
- System.out.println(f.getCanonicalPath() + "确认要删除吗?(Y/N)");
- Scanner in = new Scanner(System.in);
- String chioce = in.next();
- if (chioce.equals("Y") || chioce.equals("y")) {
- f.delete(); //删除文件
- System.out.println("文件删除成功");
- }else {
- System.out.println("文件取消删除");
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- }
- }
- import java.io.*;
- import java.util.Scanner;
-
- public class copyDome {
- public static void main(String[] args) {
- Scanner in = new Scanner(System.in);
- System.out.println("请输入源文件地址");
- String srcPath = in.nextLine();
- System.out.println("请输入目标文件地址");
- String newPath = in.nextLine();
- File srcFile = new File(srcPath); //创建源文件对象
-
- if (!srcFile.isFile()) {
- System.out.println("输入有误,不是一个文件");
- return;
- }
- //进行文件的读取和写入(拷贝):把inputStream读取到的内容复制(写入)到outputStream
- try (InputStream inputStream = new FileInputStream("srcPath")) {
- try (OutputStream outputStream = new FileOutputStream("newPath")) {
- byte[] buffer = new byte[1024]; //创建一个缓冲区用于存放数据
- while (true) {
- int len = inputStream.read(buffer); //从buffer读取所有数据
- if (len == -1) { // -1 表明数据读取完毕
- break;
- }
- outputStream.write(buffer,0,len);
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
扫描指定目录,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录)
注意:我们现在的方案性能较差,所以尽量不要在太复杂的目录下或者大文件下实验
- import java.io.File;
- import java.io.FileReader;
- import java.io.IOException;
- import java.io.Reader;
- import java.util.Scanner;
-
- public class scanDemo {
- public static void main(String[] args) throws IOException {
- Scanner in = new Scanner(System.in);
- System.out.println("输入要扫描的路径:");
- String rootDirPath = in.nextLine();
- System.out.println("输入要查找的关键词:");
- String words = in.nextLine();
- File rootDir = new File(rootDirPath); //创建目录下的文件夹对象
- if (!rootDir.isDirectory()) {
- System.out.println("输入的路径不正确");
- return; //退出
- }
-
- scanDir(rootDir,words); //遍历目录,查找关键字对应的文件
- }
-
- private static void scanDir(File rootDir,String words) throws IOException {
- File[] files = rootDir.listFiles(); //列举出rootDir文件夹下对应的所有文件
- if (files == null) {
- return;
- }
- for (File f: files) { //遍历所有文件
- if (f.isFile()) {
- if (containsWords(f,words)) {
- System.out.println(f.getCanonicalPath()); //输出对应的路径
- }
- } else if (f.isDirectory()) {
- scanDir(f,words);
- }
- }
- }
-
- private static boolean containsWords(File f,String words) {
- StringBuilder stringBuilder = new StringBuilder();
- try(Reader reader = new FileReader(f)) { //字符流读取数据
- char[] chars = new char[1024];
- while (true) {
- int len = reader.read(chars);
- if (len == -1) {
- break;
- }
- stringBuilder.append(chars,0,len); //把读取到的数据放到stringBuilder
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- return stringBuilder.indexOf(words) != -1; //indexOf返回字串的下标
- }
- }