Java的File与IO流

目录

 

一、File类

 1.构造器

 2.常用方法

二、IO流

1.常见字符集

2.IO流体系

2.1原始流

1.FileInputStream

1.1常用构造器

1.2常用方法

2.FileOutputStream

2.1常见构造器

2.2常用方法

2.3文件复制

​编辑

3.FileReader

3.1常用构造器

3.2常用方法

4.FileWriter

4.1常见构造器

4.2常用方法

2.2包装流

1.缓冲流

1.1BufferedInputStream

1.1.1常用构造器

1.1.2常用方法

1.2BufferedOutputStream

1.2.1构造器

1.2.2常用方法

1.3BufferedReader

1.3.1构造器

1.3.2常用方法

1.4BufferedWriter

1.4.1构造器

1.4.2常用方法

2.转换流

2.1InputStreamReader

2.1.1构造器

2.1.2常用方法

2.2OutputStreamWriter

2.2.1构造器

2.2.2常用方法

3.打印流

3.1PrintStream

3.1.1构造器

3.1.2常用方法

3.2PrintWriter

3.2.1构造器

3.2.2常用方法

3.2.3输出语句重定向

4.数据流

4.1DataInputStream

4.1.1构造器

4.1.2常用方法

4.2DataOutputStream

4.2.1构造器

4.2.2常用方法

5.序列化流

5.1ObjectInputStream

5.1.1构造器

5.1.2常用方法

5.2ObjectOutputStream

5.2.1构造器

5.2.2常用方法

6.对比 

3.Commons-io


 

一、File类

JDK17API中文文档java.io.File类

File类位于java.io包下,是文件和目录路径名的抽象表示,提供了一系列对文件和文件夹本身操作的方法,它不能读写数据。JDK7之后,java.nio.file包下提供了功能更灵活的Path类和Files类替代java.io.File类。

注意:File类是路径名的抽象表示,构建一个File实例并不会创建一个文件,不管文件是否存在,都可以创建任意文件名的File实例。

绝对文件名:文件名+完整路径+盘符

相对文件名:相对于当前工作目录

 

UNIX系统使用正斜杠'/'作为目录分隔符;

Windows系统使用反斜杠'\'作为目录分隔符,为了与转义字符区分,书写时使用双反斜杠'\\';

File类中可以通过File.separator字段获取当前系统的分隔符。

 

Java中的目录分隔符是正斜杠'/',支持在任何系统使用。

 1.构造器

public File(String  pathname) 根据路径名创建File对象

File file = new File("D:/practice/dd.txt");//使用了一个不存在的文件路径
System.out.println(file.exists());//false,判断文件是否存在

 2.常用方法

判断文件类型、获取信息

public boolean exists()   文件或目录是否存在

public boolean isFile()   文件是否为普通文件

public boolean isDirectory()   文件是否为目录

public String  getName()  文件或目录的名称

public long length()  文件的长度

public long lastModified()  最后修改时间

public String  getPath()  创建文件对象时的路径

public String  getAbsolutePath()  返回此抽象路径名的绝对路径名字符串

File file1 = new File("D:/practice/aa.txt");
        System.out.println(file1.isFile());//true,判断是不是文件
        System.out.println(file1.isDirectory());//false,判断是不是文件夹
        System.out.println(file1.getName());//aa.txt,获取文件名,包含后缀
        System.out.println(file1.length());//6,获取文件大小(字节),long类型
        System.out.println(file1.lastModified());//1741874577676,从UNIX时间开始计算的毫秒值,long类型
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");//简单日期格式化器
        System.out.println(sdf.format(file1.lastModified()));//2025年03月13日 22:02:57
        System.out.println(file1.getAbsolutePath());//D:\practice\aa.txt,获取绝对路径
        System.out.println(file1.getPath());//D:\practice\aa.txt,获取创建File对象时使用的路径

 创建、删除文件

public boolean createNewFile() throws IOException 文件不存在时创建新文件

public boolean mkdir() 创建一级文件夹

public boolean mkdirs() 创建多级文件夹

public boolean delete()  删除文件或空文件夹,且不会进入回收站

File file = new File("D:/practice/dd.txt");//使用了一个不存在的文件路径
        System.out.println(file.exists());//false,判断文件是否存在
        file.createNewFile();//创建文件,需要抛出异常
        File dir = new File("D:/practice/dd");
        dir.mkdir();//创建一级文件夹
        File dir1 = new File("D:/practice/aa/bb/cc");
        dir1.mkdirs();

遍历文件夹

public String [] list()  一级文件名(只有文件名)数组

public File [] listFiles()  一级文件对象数组,包含隐藏文件,无权限访问则为null,主调为文件也为null

File file2 = new File("D:/practice");
        String[] f1 = file2.list();
        for (int i = 0; i < f1.length; i++) {
            System.out.println(f1[i]);
        }
        System.out.println("--------------");
        File[] f2 = file2.listFiles();
        for (int i = 0; i < f2.length; i++) {
            System.out.println(f2[i]);
        }
        /*
        *   aa
            aa.txt
            dd
            dd.txt
            FSCapture.exe
            --------------
            D:\practice\aa
            D:\practice\aa.txt
            D:\practice\dd
            D:\practice\dd.txt
            D:\practice\FSCapture.exe
        * */

 使用广度优先查找子文件

public static boolean searchFile(File rootFile, String targetFileName) {
        Queue<File> queue = new LinkedList<>();
        queue.add(rootFile);

        while (!queue.isEmpty()) {
            File currentFile = queue.poll();
            File[] children = currentFile.listFiles();

            if (children == null) {
                continue; // 跳过无法访问的目录
            }

            for (File child : children) {
                if (child.isDirectory()) {
                    queue.add(child); // 如果是目录,加入队列
                } else if (child.getName().equals(targetFileName)) {
                    System.out.println("找到了: " + child.getAbsolutePath());
                    return true; // 找到文件,直接返回
                }
            }
        }

        return false; // 未找到文件
    }

二、IO流

java.io包下,用于读写数据(文件、网络数据等)。

1.常见字符集

计算机文件本质上是由二进制数据组成的。为了将二进制数据转换为可读字符,需要为每个字符分配特定的二进制编码,由此产生了字符集概念。目前常见的字符集包括ASCII、GBK和Unicode,这些字符集都保持了对ASCII编码的向下兼容性。

ASCII:每个字符占1个字节,首位为0,能表示128个字符。

GBK:中文字符占2个字节,ascii字符占一个字节,且中文字符首位为1.

Unicode:万国码,UTF-32使用4个字节表示一个字符;

                UTF-8采用变长编码表示字符,设置了4个长度区:

字节数编码格式(二进制)说明
1 字节0XXX XXXX兼容 ASCII(0~127)
2 字节110X XXXX 10XX XXXX扩展拉丁文、希腊文等
3 字节1110 XXXX 10XX XXXX 10XX XXXX涵盖绝大多数汉字
4 字节1111 0XXX 10XX XXXX 10XX XXXX 10XX XXXX特殊符号、emoji 等

编码是将字符按指定字符集转成字节,

解码是将字节按指定字符集转成字符。

使用String的getBytes()获取字节数组,使用String的构造器将字节数组转换成字符串。

2.IO流体系

IO流可以分为输入流和输出流,或者字节流和字符流。

IO流使用完毕之后都需要关闭,一般调用close方法关闭,也可以使用try-with-resource实现自动关闭。

2.1原始流

1.FileInputStream

文件字节输入流,继承自InputStream,适合做文件复制的操作。

1.1常用构造器

FileInputStream(文件对象)

FileInputStream(路径名)  //底层同样使用File对象,又简洁,所以更加常用

@Test
public void testFileInputStream() {
    try (FileInputStream fis1 = new FileInputStream("src\\main\\resources\\a.txt");
         FileInputStream fis2 = new FileInputStream(new File("src\\main\\resources\\a.txt"))
    ) {
        System.out.println(fis1);
        System.out.println(fis2);
    }catch (Exception e){
        System.out.println("文件未找到");
    }
}

1.2常用方法

方法描述
public int read()读1个字节,返回读取的字节,没有数据则返回-1
public int read(byte[] buffer)读最多buffer.length的数据,有数据返回读取的字节数,无数据则返回-1
public byte[] readAllBytes()(继承自InputStream)一次性读取流的所有字节,无数据则返回空字节数组

a.txt文件中为hello world

read()读一个字节可以拿到h

@Test
public void testFileInputStream2() {
    try (FileInputStream fis1 = new FileInputStream("src\\main\\resources\\a.txt")
    ) {
        int byte1 = fis1.read();
        System.out.println((char) byte1);
    }catch (Exception e){
        System.out.println("文件未找到");
    }
}

再循环读取,拿到所有字节

@Test
public void testFileInputStream2() {
    try (FileInputStream fis1 = new FileInputStream("src\\main\\resources\\a.txt")
    ) {
        int byte1;
        while ((byte1 = fis1.read()) != -1) {
            System.out.print((char) byte1);
        }
    }catch (Exception e){
        System.out.println("文件未找到");
    }
}

read(字节数组)一次性读取多个字节,注意要判断实际读取的字节到底有多少,以免错误地读取字节数组之前遗留的数据。下方代码的字节数组大小设置较小,一般不会这么小,会设置成1024的倍数。

@Test
public void testFileInputStream3() {
    try (FileInputStream fis1 = new FileInputStream("src\\main\\resources\\a.txt")
    ) {
        byte[] bytes = new byte[2];
        int byteread;
        while ((byteread = fis1.read(bytes)) != -1) {
            System.out.print(new String(bytes, 0, byteread, StandardCharsets.UTF_8));
        }
    }catch (Exception e){
        System.out.println("文件未找到");
    }
}

2.FileOutputStream

文件字节输出流,将数据写入到File或FileDescriptor的输出流。

2.1常见构造器

boolean append代表是否追加,为true时追加,即不覆盖文件的已有数据而是将待写入数据追加在文件末尾。

2.2常用方法

@Test
public void testFileOutputStream(){
    try(FileOutputStream fos = new FileOutputStream("src\\main\\resources\\a.txt", true)){
        fos.write('a');//写入一个字节
        fos.write("\r\n".getBytes(StandardCharsets.UTF_8));//写入换行符,以便区分。传入了字节数组
        byte[] bytes = "你好,世界".getBytes(StandardCharsets.UTF_8);
        fos.write(bytes, 0, 6);//写入字节数组的一部分,包前不包后
    }catch (Exception e){
        System.out.println("文件未找到");
    }
}

成功写入

2.3文件复制

 在resources目录下再新建一个空的a_copied.txt文件,将文件a.txt的内容复制到a_copied.txt。

@Test
public void copy(){
    try (FileInputStream fis = new FileInputStream("src\\main\\resources\\a.txt");
         FileOutputStream fos = new FileOutputStream("src\\main\\resources\\a_copied.txt")) {
        byte[] bytes1 = new byte[1024];
        int len;
        while ((len = fis.read(bytes1)) != -1) {
            fos.write(bytes1, 0, len);
            System.out.println(new String(bytes1, 0, len, StandardCharsets.UTF_8));
        }
    }catch (Exception e){
        System.out.println("文件未找到");
    }
}

3.FileReader

文件字符输入流,继承自InputStreamReader。

3.1常用构造器

同样可以使用文件对象和路径名创建对象,此外增加了选定字符集的参数。

3.2常用方法

FileReader的方法都是继承自不同层父类的。

方法描述
public int read()读取单个字符,返回读取的字符,如果没有则返回-1
public int read(char[] cbuf)(祖父类Reader的方法)读一个字符数组,返回读取的字符数,如果没有则返回-1
@Test
public void testFileReader(){
    try (FileReader fr = new FileReader("src\\main\\resources\\a.txt")){
        int res = fr.read();//读一个字符
        System.out.print((char) res);
        char[] bytes1 = new char[10];
        int len;
        while ((len = fr.read(bytes1))!= -1) {
            System.out.print(new String(bytes1, 0, len));
        }
    }catch (Exception e){
        System.out.println("找不到文件");
    }
}

 

4.FileWriter

文件字符输出流,继承自OutputStreamWriter。

4.1常见构造器

和FileOutputStream相似,可以通过文件对象和路径构造对象,设置是否可以追加。

 

4.2常用方法

方法描述
void write(int c)写一个字符
void write(String c)写一个字符串
void write(String c, int pos, int len)写字符串的一部分
void write(char[] buffer)写一个字符数组
void write(char[] buffer, int pos, int len)写字符数组的一部分
@Test
public void testFileWriter() throws IOException {
    FileWriter fw = new FileWriter("src/main/resources/a.txt", true);
    fw.write("\r\n-------\r\n");//写入一个字符串
    fw.flush();
    fw.write(97);//写入一个字符
    fw.flush();
    fw.write("i love you", 5, 2);//写入字符串的一部分
    fw.flush();
    fw.write(new char[]{'a', 'b', 'c'});//写入一个字符数组
    fw.flush();
    fw.write(new char[]{'d', 'e', 'f'}, 0, 2);//写入字符数组的一部分
    fw.close();//关闭流
}

字符输出流写出后必须刷新流或者关闭流,才能使写出的数据生效。

字符输出流会先写到系统缓冲区(4KB~8KB),缓冲区满时会自动刷新。不要依赖这种隐式的写入,容易出现错误,必须刷新或关闭流。

2.2包装流

1.缓冲流

缓冲流是Java IO体系中用于提高I/O效率的重要工具,它们通过在内存中创建缓冲区来减少实际的物理I/O操作次数。默认缓冲池大小为8KB。

1.1BufferedInputStream

字节输入缓冲流。

1.1.1常用构造器

1.1.2常用方法

和字节输入流常用方法相似。

方法描述

int read()

读取单个字节

int read(byte[] b)

读取字节到数组

int read(byte[] b, int off, int len)

读取字节到数组的指定位置
@Test
public void testBufferedInputStream() throws IOException {
    try (InputStream in = new FileInputStream("src\\main\\resources\\a.txt");
         BufferedInputStream bis = new BufferedInputStream(in)) {
        int ch = bis.read();//读一个字节
        System.out.print((char) ch);
        System.out.println("===============");
        byte[] b1 = new byte[1024];
        int len1 = bis.read(b1, 0, 2);//将数据读到数组的指定位置
        System.out.println(new String(b1, 0, len1, StandardCharsets.UTF_8));
        System.out.println("===============");
        byte[] bytes = new byte[1024];
        int len;
        while ((len = bis.read(bytes)) != -1) {//读一个字节数组
            System.out.print(new String(bytes, 0, len, StandardCharsets.UTF_8));
        }
    }catch (Exception e){
        e.printStackTrace();
    }
}

 

1.2BufferedOutputStream

字节缓冲输出流。

1.2.1构造器

1.2.2常用方法

方法描述
void write(int b)写入单个字节
void write(byte[] b)写入字节数组
void write(byte[] b, int off, int len)写入字节数组的一部分

 

@Test
public void testBufferedOutputStream() throws IOException {
    try (OutputStream out = new FileOutputStream("src\\main\\resources\\a.txt", true);
    BufferedOutputStream bos = new BufferedOutputStream(out)) {
        bos.write("\r\n".getBytes(StandardCharsets.UTF_8));//换行
        bos.write(48);//写入单个字节
        bos.write("\r\n".getBytes(StandardCharsets.UTF_8));//换行
        bos.write("哈哈哈哈".getBytes(StandardCharsets.UTF_8));//写入字节数组
        bos.write("\r\n".getBytes(StandardCharsets.UTF_8));//换行
        bos.write("honey hou".getBytes(StandardCharsets.UTF_8), 5, 3);
    }catch (Exception e){
        e.printStackTrace();
    }
}

1.3BufferedReader

继承Reader。

1.3.1构造器

1.3.2常用方法

方法描述
int read()读取单个字符
int read(char[] cbuf)读取字符到数组
int read(char[] cbuf, int off, int len)读取字符到数组的指定位置
String readLine()(重要)读取一行文本(不包含换行符),没有则返回null

 使用readLine读取文件内容

@Test
public void testBufferedReader() {
    try (BufferedReader br = new BufferedReader(new FileReader("src\\main\\resources\\a.txt"));){
        String s = null;
        while ((s = br.readLine()) != null) {
            System.out.println(s);
        }
    }catch (Exception e){
        e.printStackTrace();
    }
}

1.4BufferedWriter

继承Writer。

1.4.1构造器

1.4.2常用方法

方法描述
void write(int c)写入单个字符
void write(char[] cbuf)写入字符数组
void write(char[] cbuf, int off, int len)写入字符数组的一部分
void write(String str)写入字符串
void write(String str, int off, int len)写入字符串的一部分
void newLine()写入平台相关的行分隔符

 

2.转换流

转换流用于在字节流和字符流之间进行转换,可以指定字符编码。

代码编码与文本编码一致,字符流读取才不会乱码。

2.1InputStreamReader

继承自Reader。字符输入转换流,字节到字符的转换流。

先获取原始字节流,再按真实字符集编码转为字符流。

2.1.1构造器

2.1.2常用方法

方法描述
int read()读取单个字符
int read(char[] cbuf)将字符读入数组
int read(char[] cbuf, int off, int len)将字符读入数组的指定位置
boolean ready()判断是否准备好读取
void close()关闭流
String getEncoding()返回此流使用的字符编码名称

2.2OutputStreamWriter

字符输出转换流,字符到字节的转换流。

2.2.1构造器

2.2.2常用方法

方法描述
void write(int c)写入单个字符
void write(char[] cbuf)写入字符数组
void write(char[] cbuf, int off, int len)写入字符数组的一部分
void write(String str)写入字符串
void write(String str, int off, int len)写入字符串的一部分
void flush()刷新流
void close()关闭流(会先调用flush)
String getEncoding()返回此流使用的字符编码名称

3.打印流

写数据出去,打印什么就是什么,不会把97转成a。

3.1PrintStream

字节打印流。继承FilterOutputStream。System.out就是一个PrintStream实例。

3.1.1构造器

PrintStream(字节输出流/文件对象/路径)

PrintStream(文件对象/路径, 字符集)

PrintStream(字节输出流, 是否自动刷新)

PrintStream(字节输出流, 是否自动刷新, 字符集)

3.1.2常用方法

方法描述
void print(各种类型)打印内容
void println()打印换行符
void println(各种类型)打印内容后换行
void write(int b/ byte[] b/ byte[] b的一部分)写入单个字节或字节数组或字节数组的一部分(继承自OutputStream)

3.2PrintWriter

 

3.2.1构造器

PrintWriter(字节输出流/字符输出流/文件对象/路径)

PrintWriter(文件对象/路径, 字符集)

PrintWriter(字节输出流/字符输出流, 是否自动刷新)

PrintWriter(字节输出流, 是否自动刷新, 字符集)

3.2.2常用方法

方法描述
所有print/println方法同PrintStream
void write(int c)写入单个字符
void write(char[] buf)写入字符数组
void write(char[] buf, int off, int len)写入字符数组的一部分
void write(String s)写入字符串
void write(String s, int off, int len)写入字符串的一部分

3.2.3输出语句重定向

使用System.setOut(PrintStream),然后跟以前一样调用System.out 

@Test
    public void testPrintWriter() {
        try (FileOutputStream fos = new FileOutputStream("src\\main\\resources\\b.txt");
             BufferedOutputStream bos = new BufferedOutputStream(fos);
             PrintStream printStream = new PrintStream(bos)) {
            System.setOut(printStream);
            System.out.println("第一句话");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

4.数据流

数据流是Java I/O体系中用于读写基本数据类型和字符串的特殊流,它们提供了与机器无关的数据存储方式。

4.1DataInputStream

数据输入流

4.1.1构造器

4.1.2常用方法

方法描述读取格式
boolean readBoolean()读取boolean值1字节
byte readByte()读取byte值1字节
short readShort()读取short值2字节
char readChar()读取char值2字节
int readInt()读取int值4字节
long readLong()读取long值8字节
float readFloat()读取float值4字节
double readDouble()读取double值8字节
String readUTF()读取UTF-8字符串前2字节长度 + UTF-8内容
int readUnsignedByte()读取无符号byte1字节(返回int)
int readUnsignedShort()读取无符号short2字节(返回int)

4.2DataOutputStream

数据输出流。

4.2.1构造器

4.2.2常用方法

方法描述写入格式
void writeBoolean(boolean v)写入boolean值1字节
void writeByte(int v)写入byte值1字节
void writeShort(int v)写入short值2字节(大端序)
void writeChar(int v)写入char值2字节(UTF-16)
void writeInt(int v)写入int值4字节(大端序)
void writeLong(long v)写入long值8字节(大端序)
void writeFloat(float v)写入float值4字节(IEEE 754)
void writeDouble(double v)写入double值8字节(IEEE 754)
void writeBytes(String s)写入字符串(按字节)每个字符低8位
void writeChars(String s)写入字符串(按字符)UTF-16编码
void writeUTF(String s)写入UTF-8编码字符串前2字节长度 + UTF-8内容

5.序列化流

用于对象的序列化和反序列化。

序列化:将对象转换为字节序列,以便存储到文件、数据库或通过网络传输,比如Java对象->JSON/XML文件。

反序列化:将字节序列重新恢复为内存中的对象。

实现了Serialization接口的对象才可以被序列化。

5.1ObjectInputStream

对象输入流,反序列化对象,继承自InputStream。

5.1.1构造器

5.1.2常用方法

方法描述
Object readObject()读取对象(反序列化)
boolean readBoolean()读取基本类型
byte readByte()读取基本类型
short readShort()读取基本类型
char readChar()读取基本类型
int readInt()读取基本类型
long readLong()读取基本类型
float readFloat()读取基本类型
double readDouble()读取基本类型
String readUTF()读取UTF-8字符串

5.2ObjectOutputStream

对象输出流,序列化对象。

5.2.1构造器

5.2.2常用方法

方法描述
void writeObject(Object obj)写入对象(序列化)
void writeBoolean(boolean val)写入基本类型
void writeByte(int val)写入基本类型
void writeShort(int val)写入基本类型
void writeChar(int val)写入基本类型
void writeInt(int val)写入基本类型
void writeLong(long val)写入基本类型
void writeFloat(float val)写入基本类型
void writeDouble(double val)写入基本类型
void writeUTF(String str)写入UTF-8字符串

6.对比 

流类型主要用途特点常用类
缓冲流提高I/O效率内置缓冲区,减少物理I/O操作BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter
打印流方便输出各种数据类型不抛IO异常,自动刷新PrintStream, PrintWriter
转换流字节流与字符流转换处理字符编码问题InputStreamReader, OutputStreamWriter
数据流读写基本数据类型保持数据类型不变DataInputStream, DataOutputStream
序列化流对象序列化/反序列化需要实现Serializable接口ObjectInputStream, ObjectOutputStream

3.Commons-io

Apache旗下的开源项目,简化了Java的IO操作。

文件操作:如文件读取、写入、复制、删除等。

流操作:对字节流和字符流的封装,简化流的使用。

文件过滤器:提供了一些常用的文件过滤器,比如根据文件扩展名过滤文件。

文件和目录的递归操作。

文件的转换:比如字节流和字符流之间的转换。

apache_commons_io教程

commons-io官方文档

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值