这一世我重生了,因为Java学的少没合适的工作而被饿死街头的我开始学习Java -- IO流文件操作

IO流文件操作

File

File类主要是Java中对文件这块的操作(如删除、修改、查询等)而设计的相关类
File类的包名是java.io,其实现了Serializable、Comparable两大接口以便于其对象可序列化和比较
File是文件和目录路径名的抽象表示,文件和目录是可以通过File封装成对象的,其封装的并不是一个真正存在的文件,仅仅是一个路径名而已。不论文件是否真的存在,都可以通过具体的操作来把File所指的文件给创建出来

import java.io.File;

public class Main {
    public static void main(String[] args) {
        // File(String pathname)
        //通过将给名的路径名字符串转换为抽象路径名来创建新的File实例
        File file1 = new File("E:\\Test\\1.txt");
        System.out.println(file1);

        // File(String parent, String child)
        // 前者为父路径名,后者为子路径名,二者进行拼接即可得到一个完整的路径名字符串,同样转换为抽象路径名来创建File实例
        File file2 = new File("E:\\Test", "aaa\\2.txt");
        System.out.println(file2);

        // File(File parent, String child)
        // 前者为父路径对象,后者为子路径名,同样可以对二者进行拼接得到一个完整的路径名字符串,并转换为抽象路径名来撞见File实例
        File fileParent = new File("E:\\Test\\bbb");
        File file3 = new File(fileParent, "3.txt");
        System.out.println(file3);
    }
}

文件的创建

主要有三个方法

  • public boolean createNewFile():创建一个文件
  • public boolean mkdir():创建一个文件夹
  • public boolean mkdirs():创建带有嵌套关系的文件夹
import java.io.File;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        File file1 = new File("E:\\IDEA\\wordSpace\\test\\test\\src\\1.txt");
        file1.createNewFile();  // 用于创建一个带有后缀的文件
        File file2 = new File("E:\\IDEA\\wordSpace\\test\\test\\src\\aaa");
        file2.mkdir(); // 用于创建单个文件夹
        File file3 = new File("E:\\IDEA\\wordSpace\\test\\test\\src\\bbb\\ccc");
        file3.mkdirs(); // 用于创建有嵌套关系的文件夹
    }
}

创建效果:

image-20250406004443638


File类中的判断方法

  • boolean isDirectory():判断是否为文件夹
  • boolean isFile():判断是否为文件
  • boolean exists():判断文件是否存在
import java.io.File;
import java.io.IOException;

public class Main {
    public static void main(String[] args) {
        // 指定目录和文件名
        String directory = "E:\\IDEA\\wordSpace\\test\\test\\src\\example";
        String fileName = "example.txt";
        try {
            // 1. 创建目录(如果不存在)
            File dir = new File(directory);
            if (dir.isDirectory() && !dir.exists()) { // 判断路径是否为文件夹且文件夹是否存在
                dir.mkdirs(); // 创建所有缺失的父目录
            }
            // 2. 创建文件
            File file = new File(dir, fileName);
            boolean isCreated = file.createNewFile();
            if (file.isFile() && isCreated) { // 判断所创建的是否为文件且文件是否已经存在
                System.out.println("文件创建成功");
            } else {
                System.out.println("文件已存在或无法创建");
            }
        } catch (IOException e) {
            e.printStackTrace(); // 处理异常
        }
        
    }
}

创建效果:

image-20250406010144293


File类的获取方法

  • String getAbsolutePath():获取绝对路径
  • String getPath():获取抽象路径名转化路径名字符串
  • String getName():获取文件或文件夹名称
  • String[] list():获取目录下所有内容,返回字符串数组
  • File[] listFiles():获取目录下所有内容,返回File对象数组

创建内容如图:

image-20250406011707198

import java.io.File;

public class Main {
    public static void main(String[] args) {
        File file1 = new File("E:\\IDEA\\WordSpace\\test\\test\\src\\example\\example1.txt");
        System.out.println(file1.getAbsoluteFile());    // 获取文件/文件夹绝对路径
        System.out.println(file1.getPath());    // 获取文件/文件夹的抽象路径并转化为字符串,和获取绝对路径类似
        System.out.println(file1.getName());    // 获取文件或文件夹名称
        System.out.println("-------------------------");
        File file2 = new File("E:\\IDEA\\WordSpace\\test\\test\\src\\example");
        String[] files1 = file2.list(); // 获取目录下的所有内容,返回字符串数组
        for (String file : files1) {    // 遍历字符串数组
            System.out.println(file);
        }
        System.out.println("-------------------------");
        File[] files2 = file2.listFiles();  // 获取目录下所有内容,返回File对象数组
        for (File file : files2) {  // 遍历File对象数组
            System.out.println(file.getName());
        }
    }
}

效果如下:

image-20250406011746089


FIle删除操作

  • boolean delete()
    若删除路径是一个目录,则不能直接删除,需要先删除该目录中所有内容后才能删除目录
    若删除路径是一个文件,则可以直接删除
// 使用循环删除
import java.io.File;

public class Main {
    public static void main(String[] args) {
        File dir = new File("E:\\IDEA\\WordSpace\\test\\test\\src\\example");
        String[] files = dir.list();    // 获取路径文件夹中的所有文件名
        for (int i = 0; i < files.length; i++) {
            File file = new File(dir, files[i]);    // 获取文件夹下的文件路径
            file.delete();  // 删除文件
        }
        dir.delete();
    }
}

// -------------------------------------------------------------------

// 使用递归删除
import java.io.File;

public class Main {
    public static void main(String[] args) {
        File dir = new File("E:\\IDEA\\WordSpace\\test\\test\\src\\aaa");
        deleteAllFiles(dir);
    }

    public static void deleteAllFiles(File file) {
        File[] files = file.listFiles();  //获取文件夹路径下的所有文件
        if (files == null) {    // 若路径下没有文件,则直接返回不用进行删除操作
            System.out.println("该路径下已无文件");
            return;
        }
        for (File f : files) {  // 遍历目录中的所有内容
            if (f.isDirectory()) {  // 若是文件夹,则递归调用本方法来进一步删除文件夹下的内容
                deleteAllFiles(f);
            } else {    // 为文件,则直接删除
                System.out.println("已删除文件:" + f.getPath());
                f.delete();
            }
        }
        file.delete();  // 最后删除文件夹
    }
}

IO流

IO:输入(Input)/输出(Output),即输入数据以及写数据
流:是一种抽象概念,是对数据传输的总称,即数据在设备间的传输称为流,流的本质是数据传输
IO流就是用来处理设备间数据传输问题的
IO流常见的应用即文件上传、下载、复制等

IO流的分类:

  1. 根据数据流向来分:
    输入流:读数据,将硬盘中的数据读取到内存中
    输出流:写数据,将程序中的数据写入到硬盘中
  2. 根据数据类型来分:
    字节流:字节输入流/字节输出流
    字符流:字符输入流/字符输出流
  3. IO应用场景:
    纯文本文件,优先使用字符流
    图片、视频、音频等二进制文件,优先使用字节流
    不确定文件类型,优先使用字节流,可以说字节流是万能流
字节流

字节流输出数据

  • InputStream:这个抽象类是表示字节输入流的所有类的超类
  • OutputStream:这个抽象类是表示字节输出流的所有类的超类
    特点:子类名称都是以其父类名作为子类名的后缀
  • FileOutputStream:文件输出流用于将数据写入File
  • FileOutputStream(Stringname):创建文件输出流以指定的名称写入文件

输出流步骤:
1、调用系统功能创建了文件
2、创建字节输出流对象
3、字节输出流对象指向文件

字节流写入数据常用的三种方式:

  • void write(int b):将指定的字节写入此文件输出流,一次写一个字节数据
  • void write(byte[] b):将b.length字节从指定的字节数组写入此文件输出流,一次写一个字节数组数据
  • void write(byte[] b, int off, int len):将len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流,一次写一个字节数组部分的数据
import java.io.FileOutputStream;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        FileOutputStream fileOutputStream1 = new FileOutputStream("src\\1.txt");
        fileOutputStream1.write(97);    // 一个一个的写入
        fileOutputStream1.write(98);	// 这里的数据不一定是数字类型,直接使用字符也是可以的
        fileOutputStream1.write(99);
        FileOutputStream fileOutputStream2 = new FileOutputStream("src\\2.txt");
        byte[] bytes = {97,98,99,100};
        fileOutputStream2.write(bytes); // 将bytes中的所有数据直接写入
        fileOutputStream2.write("this is a test".getBytes());   // 通过getBytes()方法写入
        FileOutputStream fileOutputStream3 = new FileOutputStream("src\\3.txt");
        fileOutputStream3.write(bytes, 1, bytes.length - 1);    // 从bytes的第一个元素开始写入到最后一个元素

        fileOutputStream1.close();
        fileOutputStream2.close();
        fileOutputStream3.close();
    }
}

字节流数据若要换行则可以使用转义字符\r\n都可以

字节流数据若要追加写,则可以通过使用FIleOutPutStream(File, true))
其中表示第二个参数若为true,则字节流写入文件的末尾

import java.io.FileOutputStream;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        FileOutputStream f = new FileOutputStream("src\\1.txt", true);	// 设置第二个参数为true,表示可以进行持续写入
        f.write(("This is test1").getBytes());
        f.write('\n');
        f.write(("This is test2").getBytes());
        f.close();
    }
}

上面的代码中都发现了一个函数,即close(),该函数可以释放文件资源,但需要规范使用:

  1. 当文件为null时是不能释放资源的
  2. 当文件已经打开使用,程序遇到报错而中断时,同样需要进行资源的释放
import java.io.FileOutputStream;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        FileOutputStream f = null;
        try {
            f = new FileOutputStream("src\\test.txt");
            f.write(("This is a test").getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {     // 使用finally关键字,即使程序在运行过程中出现报错而中断都会继续运行
            if (f == null) {
                try {
                    f.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

字节流读取数据

上面介绍了如何将内容写入磁盘中,而将磁盘文件中的数据读取出来的话,可以使用到

  1. FileInputStream:从文件系统中的文件获取输入字节
  2. FileInputStream(Stringname):通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的路径名name命名

读取数据步骤:
1、创建字节输入流对象
2、调用字节输入流对象的读数据方法
3、释放资源

字节流读取磁盘文件数据的常见方法:

  • int read():从该输入流读取一个字节数据,返回值为-1时说明文件读取完毕
import java.io.FileInputStream;

public class Main {
    public static void main(String[] args) {
        FileInputStream f = null;
        try {
            f = new FileInputStream("src\\test.txt");
            int read = f.read();
            while (read != -1) {    // 循环读取,当f.read == -1时表示文件已全部读取完毕
                System.out.print((char) read);  // 将读取的int类型数据转换为char类型
                read = f.read();    // 持续循环读取下一个数据
            }
            
            /*
            * int read;
            * while ((read = f.read()) != -1) {
            *    System.out.print((char) read);
            * } 
            * 或者这样同样也可以对磁盘文件数据进行循环读取
            * */
            
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                f.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

了解了数据的读取后,就很轻松的能够实现将一个文件的数据复制到另一个文件中了

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class Main {
    public static void main(String[] args) {
        FileInputStream input = null;
        FileInputStream output = null;
        try {
            input = new FileInputStream("src\\test.txt");
            output = new FileInputStream("src\\1.txt");
            int read;
            while ((read = input.read()) != -1) {
                FileOutputStream clone = new FileOutputStream("src\\1.txt", true);
                clone.write(read);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                input.close();
                output.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

上述字节流数据读取都使用到了循环读取,使用循环读取单次只能读取一个数据,就好比你需要喝水,此时饮水机在滴水,然后你对着龙头一滴一滴的喝,这样效率是很差的
我们一般都是使用一个容器,先把装水装进来,然后再一次性喝下去,这样的效率就会高很多。于是对于字节流数据的读取就可以使用字节流读取字节数组数据

// 文本的复制
import java.io.FileInputStream;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        FileInputStream f = new FileInputStream("src\\test.txt");
        byte[] buf = new byte[1024];	// 将数据全部存入字节数组中
        int len = f.read(buf);	// 利用字节流读取字节数组数据
        System.out.println(new String(buf, 0, len));
        f.close();
    }
}

// ---------------------------------------------------

// 图片的复制
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        FileInputStream input = new FileInputStream("src\\test.jpg");
        byte[] buf = new byte[1024];
        int len;
        FileOutputStream output = new FileOutputStream("src\\1.jpg");
        while ((len = input.read(buf)) != -1) {
            output.write(buf, 0, len);
        }
        input.close();
        output.close();
    }
}

对于字节数组的大小,通常定义为1024的整数倍,因为1024正好代表1kb的数据

字节缓冲流

用专业术语来说的话:
传统方式一个字节一个字节读取或者写入数据,会频繁的发生系统内核的调用(用户态与内核态之间的切换),效率十分的低下
于是我们可以使用到字节缓冲流,缓冲区是一个内存区域的概念,以块为单位写入或读取数据,用来减少系统的调用频率

  • BufferedInputStream(InputStream in):字节缓冲输入流
  • BufferedOutputStream(OutputStream out):字节缓冲输出流

和一般字节流不同的是,字节缓冲流对象的构造函数传递字节流对象,并不是文件路径,缓冲流提供了一个缓冲去,做好了封装,以块的形式读写数据,但腹泻数据依然依赖于字节流对象

注意:字节缓冲流的缓冲区大小默认为8kb,即8192字节

对于字节缓冲流的使用,其实是比较简单的

import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        // 创建字节输入缓冲流
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("src\\test.jpg"));
        // 创建字节输出缓冲流
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("src\\1.jpg"));
        int len;
        byte[] buf = new byte[1024];    // 创建缓冲块
        while ((len = bis.read(buf)) != -1) {	// 持续按缓冲块读取文件数据
            bos.write(buf, 0, len);		// 持续按缓冲块写文件数据
        }
        bis.close();
        bos.close();
    }
}
字符流

字符流,实际上是对字节流的包装,像是读取文件、文本类型优先使用字符流,它可以对文件去做一些编码和解码

  • Writer是写入字符流的抽象类
    OutputStreamWriter(输出转换流):为字符流通向字节流的桥梁,将要写入流的字符编码成字节
    构造方法1:OutputStreamWriter(OutputStream out):用于创建使用默认字符编码的OutputStreamWriter
    构造方法2:OutputStreamWriter(OutputStream out, String charseName):用于创建使用默认字符编码的OutputStreamWriter

字符流的底层还是用字节流进行读写,字符流仅仅是做了字节和字符的转换,即编码与解码
接收字符数据,首先要把字符数据变成字节数据,然后再用普通字节流,把数据写到硬盘,以此实现字符数据转换为字节数据

  • Reader是用于读取字符流的抽象类
    InputStreamReader(输入转换流):为字节流通向字符流的桥梁,将读取字节并将其解码成字符
    构造方法1:InputStreamReader(InputStream in):用于创建一个使用默认字符集的InputStreamReader
    构造方法2:InputStreamReader(InputStream in, String charserName):用于创建使用指定字符集的InputStreamReader

接收字节流,转换成字符流,底层会用字节流去硬盘读取字节数据,把字节数据转换为字符数据,然后返回,以此实现字节数据转换为字符数据

import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        // 字符输入流
        InputStreamReader isr = new InputStreamReader(new FileInputStream("src\\test.txt"));
        // 字符输出流
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("src\\1.txt"));
        char[] buf = new char[1024];    // 创建缓冲区
        int len;
        while ((len = isr.read(buf)) != -1) {
            osw.write(buf, 0, len); // 将读取到的文本内容写入到1.txt下
        }
        isr.close();
        osw.close();
    }
}

转换流的便捷形式FileWriterFileReader:使用更为便捷

import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        // 字符输入流
        FileReader fr = new FileReader("src\\test.txt");
        // 字符输出流
        FileWriter fw = new FileWriter("src\\1.txt");
        char[] buf = new char[1024];    // 创建缓冲区
        int len;
        while ((len = fr.read(buf)) != -1) {
            fw.write(buf, 0, len); // 将读取到的文本内容写入到1.txt下
        }
        fr.close();
        fw.close();
    }
}

字符缓冲流

与字节缓冲流一样的道理,字符同样也有缓冲流

  • BufferedReader:从字符输入流读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取
  • BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入
  • FileReaderFileWriter:内部使用InputStreamReader、InputStreamWriter,解码过程由字节变为字符,默认的缓存大小为8kb
  • BufferReaderBufferWriter:字符缓冲写入流、字符缓冲输入流。默认缓存大小为8kb,可以手动指定缓存大小,把数据读取到缓存中,减少每次转换过程,使效率更高
import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("src\\test.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("src\\test2.txt"));
        String line;
        while ((line = br.readLine()) != null) {
            bw.write(line);
        }
        br.close();
        bw.close();
    }
}

上面这种就是读取文本文件中数据最简单的形式了

至此IO流文件操作的学习到此结束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值