Java文件操作/IO

一.什么是文件?

文件是一种在硬盘上存储数据的方式,操作系统帮我们把硬盘的一些细节都封装起来了,程序员只需要了解文件相关的接口即可,相当于操作文件就是间接的操作硬盘了,
硬盘用来存储数据,和内存相比硬盘的存储空间更大,访问速度更慢,成本更低,持久化存储,操作系统通过“文件系统”这样的模块来管理硬盘

别看我电脑上有c盘d盘,但是我电脑只装载着一块硬盘,操作系统可以通过文件系统把这个硬盘抽形成多个硬盘就如我的CD两盘,NTFS是windows上的文件系统,背后有一定的格式来组织硬盘的数据,EXT4是Linux上的文件系统

不同的文件系统管理文件的方式都是类似的
通过目录(directory,平常叫文件夹,专业术语叫目录)构成了N叉树的树形结构
我们在文件系统中都是通过路径来确定一个具体的文件

 

同样是一个cat.jpg文件,站在不同的基准目录上,查找的路径是不相同的

文件系统上存储的文件,具体来说又分成两大类


1.文本文件–存储的是字符
字符怎么定义呢?
有个表叫utf8,这个表上数据的组合就是字符
2.二进制文件–存储的是二进制数据
判断文本文件和二进制文件最简单的方式就是
直接用记事本打开,如果打开之后能看懂,就是文本,否则就是二进制像word文档,ppt,excel这些,如果托到记事本上,都是二进制文件,虽然word文档里存的东西是汉字等可以看懂的内容,但是word文档不仅仅包含我们自己输入的内容,还有行间距,文字格式等众多内容
但是如果把excel的后缀改成csv格式,就是文本文件了

utf8是文件的编码格式,此时一个汉字是三个字节的大小,在java中采用的编码格式是unicode,一个汉字是两字节的大小正好能放进char类型,那么java操作文件的时候不做处理肯定会出现问题,但是JVM已经处理好了

二.Java标准库中的操作文件类

操作文件可以理解成通过java代码把你硬盘的文件删除修改创建等,也就是通过java代码操作文件系统


Java 中通过 java.io.File 类来对一个文件(包括目录)进行抽象的描述。注意, File 对象可以对应到一个真实存在的文件,也可以对应到一个不存在的文件

 所有外部设备(包括硬盘)向系统传输数据的过程,对CPU 而言都属于"输入操作"。

File类里面的方法 

 获得文件路径

import java.io.File;
import java.io.IOException;

public class Demo {
    public static void main(String[] args) throws IOException {
        //File file = new File ("D:\\JavaEE\\java-ee-beginner\\test.txt");//绝对路径
        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());//获得规范路径(去除..等)

    }
}

创建文件和判断文件 

import java.io.File;
import java.io.IOException;

public class Demo {
    public static void main(String[] args) throws IOException {
        File file = new File("D:\\JavaEE\\java-ee-beginner\\test.txt");

        file.createNewFile();// 创建文件

        System.out.println(file.exists());// 判断文件是否存在
        System.out.println(file.isFile());// 判断是否是文件
        System.out.println(file.isDirectory());// 判断是否是目录
    }
}

 文件跟目录的区别可以认为是文件是这个路径的终点,而目录下面还有别的路径

删除文件

import java.io.File;

public class Demo {

public static void main(String[] args) {
        File file=new File("./test.txt");
        file.delete();
    }
}
import java.io.File;

public class Demo {

public static void main(String[] args) throws InterruptedException {
        File file=new File("./test.txt");
        //不是立刻删除,等到程序运行结束再删除
        file.deleteOnExit();
        Thread.sleep(2000);
        //程序运行两秒会结束,所以这个文件在两秒之后删除
    }
}

创建目录

public static void main(String[] args) {
        File file1 = new File("./testDir");

        File file2 = new File("./testDir/111/222");

        // mk => make    dir => directory
        // mkdir 一次只能创建一层目录.  mkdirs 可以一次创建多级目录
        file1.mkdir();

        //file2.mkdirs();//创建多级目录
    }

 列出目录内容

mport java.io.File;
import java.util.Arrays;

public class Demo4 {
    public static void main(String[] args) {
        //File file = new File("./test.txt");

        /*//文件是无法进行list(列出当前目录下的文件)
        String[] list = file.list();
        System.out.println(Arrays.toString(list));*/

        File file = new File("D:\\JavaEE\\java-ee-beginner");

        String[] list = file.list();//列出当前目录下的文件
        System.out.println(Arrays.toString(list));

        File[] files = file.listFiles();//列出当前目录下的文件(前缀带路径) 用File来接受
        System.out.println(Arrays.toString(files));
    }
}

文件重命名

import java.io.File;

public class Demo {
    public static void main(String[] args) {
        File file = new File("./test.txt");
        File file2 = new File("./test2.txt");

        boolean result = file.renameTo(file2);//把file重命名为file2
       
    }
}
mport java.io.File;

public class Demo {
    public static void main(String[] args) {
        /*File file = new File("./test.txt");
        File file2 = new File("./test2.txt");

        boolean result = file.renameTo(file2);//把file重命名为file2*/

        File file = new File("./test2.txt");
        File nweFile = new File("D:\\JavaEE\\java-ee-beginner\\20250607-File\\test2.txt");

        boolean result = file.renameTo(nweFile);//重命名操作还能起到移动文件的作用
        /**
         * 从操作系统的角度来看,重命名操做和移动操作(剪切)本质是一致的 移动操作极快,时间复杂度o1 (如果跨硬盘了就很慢了(复制+删除))
         * 复制文件,时间复杂度o(n),文件/目录里所有的数据,遍历,再写入写的文件/目录
         */
        System.out.println(result);
    }
}

对文件内容操作

 

 

 Reader类

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

// Reader 使用.
public class Demo
{
    public static void main(String[] args) throws IOException
    {
        // FileReader 构造方法, 可以填写一个文件路径(绝对路径/相对路径都行), 也可以填写一个构造好的 File 对象
//        Reader reader = new FileReader("。/test.txt");
//        try {
//            // 中间的代码无论出现啥情况, close 都能保证执行到.
//        } finally {
//            // 抛出异常, 或者 return, close 就都执行不到了~~
//            reader.close();
//        }

        // 上述使用 finally 的方式能解决问题, 但是不优雅.
        // 使用 try with resources 是更好的解决方案.

        try (Reader reader = new FileReader("d:/test.txt"))
        {
              while (true) {//一直
               /* int c = reader.read();//返回值int(最大值0xFFFF两个字节的最大值)
                if (c == -1) {
                    break;
                }
                System.out.println((char) c);*/

                char[] buf = new char[1024];//可以起到一个缓冲区的作用
                int n = reader.read(buf);
                if (n == -1) {
                    break;
                }

                for (int i = 0; i < n; i++) {
                    System.out.println(buf[i]);
            }
        }
    }
}

 

 

 InputStream类

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class Demo {
    public static void main(String[] args) throws IOException {
       
        try (InputStream inputStream = new FileInputStream("./test.txt")) {//出了try块,资源会自动释放,相当于自动调用inputStream.close()

            //读文件操作
            while (true) {
                /*int date = inputStream.read();//不带参数表示读取一个字节
                if (date == -1) {
                    //读完文件
                    break;
                }
                System.out.printf("0x%x\n", date);*/

                //一次读取多个字节,数组长度进行自定义
                byte[] bytes = new byte[3];
                //读操作,就会尽可能把字节数组给填满
                //填不满的话,能填几个就是几个
                int len = inputStream.read(bytes);
                System.out.println("len= " + len);
                //len就是表示实际读取了几个字节
                if (len == -1) {
                    //读完文件
                    break;
                }

                for (int i = 0; i < len; i++) {
                    System.out.printf("0x%x \n", bytes[i]);//打印每个字节的十六进制数
                }

                System.out.println("===========");
            }

        }
    }
}

于是我们可以借助Scanner来完成上述操作
平时我们输入是
Scanner scanner=new Scanner(System.in);

那么system.in的类型也是一个InputStream

 所以就有以下操作

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;

public class Demo {
    public static void main(String[] args) throws IOException 
    {
        try (InputStream inputStream = new FileInputStream("./test.txt")) 
        {
            Scanner scanner = new Scanner(inputStream);
            // 此时就是从 test.txt 这个文件中读取数据了!!
            String s = scanner.next();
            System.out.println(s);
        }
    }
}

Scanner只是用来读取文本文件,不适合读取二进制文件,标准库中需要用到一些其他类

Write类

mport java.io.*;


public class Demo {
    public static void main(String[] args) {
        try (Writer writer = new FileWriter("./output.txt", true)) {//true是实现第二次输入的时候能够拼接第一次的输入
            //writer.write("666");

            BufferedWriter bufferedWriter = new BufferedWriter(writer);//带缓冲区的流
            bufferedWriter.write("777");//将内容写到缓冲区去里
            bufferedWriter.flush();//将缓冲区里的内容写入文件
            bufferedWriter.close();//可以放到try块里 自动关闭流


        } catch (IOException e) {
            e.printStackTrace();
        }
      

    }
}


         * 缓冲区通常是一段内存的运行空间 提高编程效率 减少磁盘IO操作 但是在一些特殊情况下 如网络传输 数据库操作等 就需要使用非缓冲区的流 如FileWriter(false)
         * 因此进行IO的时候就希望能使用缓冲区把要写的数据先放到缓冲区里 攒一波再一起写
         * 或者读取的时候也不是一个一个的读 而是一次读取一批数据 放到缓冲区再慢慢解析
         * 当前IO流 read和write就是属于直接读取文件了 想要提升效率
         * 1.手动创建缓冲区 byte[]手动减少read和write的次数
         * 2.就需要使用缓冲区流 如BufferedInputStream和BufferedOutputStream
         

 OutputStream和Write使用方式完全一样,但是Write不支持字符串参数,只能按照字节或字节数组进行输出写入

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值