File类与I/O流

一、File文件操作类

概念: java.io.File类是文件和目录路径的抽象表示,主要用于文件本身操作(创建、删除、取得信息…),与平台无关。

1.构造方法

方法功能
public File(String pathname)通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例
public File(String parent, String child)父路径名字符串和子路径名字符串创建新的 File实例
public File(File parent, String child)从父抽象路径名和子路径名字符串创建新的 File实例
// 文件路径名(文件)
String pathname = "D:\\aaa.txt"; //相对路径:相对于当前module
File file1 = new File(pathname);
     
// 文件路径名(目录) 
String pathname2 = "D:\\aaa\\bbb.txt"; //绝对路径:包含盘符在内的文件或文件目录的路径 
File file2 = new File(pathname2); 

// 通过父路径和子路径字符串  
String parent = "d:\\aaa";  
String child = "bbb.txt";  
File file3 = new File(parent, child); 
  
// 通过父级File对象和子路径字符串 
File parentDir = new File("d:\\aaa"); 
String child = "bbb.txt"; 
File file4 = new File(parentDir, child);

补充:

  1. 一个File对象代表硬盘中实际存在的一个文件或者目录。
  2. 无论该路径下是否存在文件或者目录,都不影响File对象的创建。

2.常用普通方法

方法功能
public boolean createNewFile() throws IOException创建一个新文件
public boolean exists()判断文件是否存在
public boolean delete()删除文件
public class Test {
    public static void main(String[] args) {
        File file = new File("D:"+File.separator+"test"+File.separator+"hello world.txt");
        if (file.exists()){
            //文件存在,进行删除
            file.delete();
        }
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.目录操作之目录的创建与删除

方法名功能
public String getParent()获取父路径
public File getParentFile()获取父File对象
public boolean mkdirs()创建多级目录
import java.io.File;
import java.io.IOException;

public class Test {
    public static void main(String[] args) {
        File file = new File("D:"+File.separator+"test"+File.separator+"hello world.txt");
        if (!file.getParentFile().exists()){
            file.getParentFile().mkdirs();//如果父路径不存在就创建多级目录
        }
        if (file.exists()){
            file.delete();//如果文件存在就进行删除
        }
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

4.目录操作之目录的遍历

方法名功能
public String[] list()返回一个String数组,表示该File目录中的所有子文件或目录
public File[] listFiles()返回一个File数组,表示该File目录中的所有的子文件或目录
public class FileFor {
    public static void main(String[] args) {
        File dir = new File("d:\\java_code");
      
        //获取当前目录下的文件以及文件夹的名称。
        String[] names = dir.list();
        for(String name : names){
            System.out.println(name);
        }
        //获取当前目录下的文件以及文件夹对象,只要拿到了文件对象,那么就可以获取更多信息
        File[] files = dir.listFiles();
        for (File file : files) {
            System.out.println(file);
        }
    }
}

注:调用listFiles()方法的File对象,表示的必须是实际存在的目录,否则返回null,无法进行遍历。

5.取得文件信息

方法名功能
public boolean isFile()判断路径是否是文件
public boolean isDiretory()判断路径是否是目录
public long length()取得文件大小(字节)
public long lastModified()最后一次修改日期
import java.io.File;

public class Test {
    public static void main(String[] args) {
        File file = new File("C:"+File.separator+"Desktop");
        listAllFiles(file);
    }

    private static void listAllFiles(File file) {
        if (file.isDirectory()){//是目录
            File[] result = file.listFiles();//列出该级目录内容
            if (result != null){
                for (File file1 : result){
                    listAllFiles(file1);
                }
            }
        }else {
            //是文件直接打印
            System.out.println(file);
        }
    }
}

二、I/O流概述

1.什么是IO?

数据在内存硬盘间的读取和写入。

2.流的分类

  • 按流的数据单位不同分为:字节流(8bit),字符流(16bit)
  • 按数据的流向(以内存为参考点)不同分为:输入流和输出流
  • 按流的角色的不同分为:节点流,处理流
(抽象基类)字节流字符流
输入流InputStreamReader
输出流OutputStreamWriter
  1. Java的IO流共涉及40多个类,实际上非常规则,都是从这四个抽象基类派生的
  2. 由这四个类派生出来的子类名称都是以其父类名作为子类名后缀

三、字节流

1.一切皆字节

一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都是一个一个的字节,那么传输时一样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据。

2. 字节输出流【OutputStream】

java.io.OutputStream抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到目的地。它定义了字节输出流的基本共性功能方法。

方法名功能
public void close()关闭此输出流并释放与此流相关联的任何系统资源
public void flush()刷新此输出流并强制任何缓冲的输出字节被写出
public void write(byte[] b)将 b.length字节从指定的字节数组写入此输出流
public void write(byte[] b, int off, int len)从指定的字节数组写入 len字节,从偏移量 off开始输 出到此输出流

注: close方法,当完成流的操作时,必须调用此方法,释放系统资源。

3.FileOutputStream–文件字节输出流

功能: 把内存中的数据写入到硬盘的文件中
3.1构造方法

方法名功能
public FileOutputStream(File file)创建文件输出流以写入由指定的 File对象表示的文件
public FileOutputStream(String name)创建文件输出流以指定的名称写入文件

参数: 写入数据的目的地

  • String name:目的地是一个文件的路径
  • File file:目的地是一个文件

构造方法的作用:

  • 创建一个FileOutputStream对象
  • 会根据构造方法中传递的文件/文件路径,创建一个空的文件
  • 会把FileOutputStream对象指向创建好的文件

注意:
当创建一个流对象时,必须传入一个文件路径。该路径下,如果没有这个文件,则会自动创建该文件。如果有这个文 件,会清空这个文件的数据。

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

public class Test {
    public static void main(String[] args) throws FileNotFoundException {
        //使用File对象创建流对象
        File file = new File("a.txt");
        FileOutputStream fos1 = new FileOutputStream(file);
        
        //使用文件名创建流对象
        FileOutputStream fos2 = new FileOutputStream("b.txt");
    }
}

3.2写入字节
写入数据的原理:(内存–>硬盘)
java程序–>JVM(Java虚拟机)–>OS(操作系统)–>OS调用写数据的方法–>把数据写入到文件中
字节输出流的使用步骤【重点】:

  1. 创建一个FileOutputStream对象,构造方法中传入写入数据的目的地。
  2. 调用FileOutputStream对象的方法write,把数据写入到文件中。
  3. 释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提高程序的效率)。

3.2.1写入字节数据

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

public class Test {
    public static void main(String[] args) throws IOException {
        //使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("fos.txt");
        //写出数据
        fos.write(97);
        //关闭资源
        fos.close();
    }
}
//输出结果:a

注意: 虽然参数为int类型四个字节,但是只会保留一个字节的信息写出。
在这里插入图片描述
3.2.2写入字节数组
write(byte[] b):每次可以写出数组中的数据。

  • 如果写的第一个字节是正数(0~127),那么显示的时候会查询ASCII码表
  • 如果写的第一个字节是负数,那第一个字节会和第二个字节组成一个中文显示,查询系统默认码表(GBK)

面试题: 在文件中写入100,要写入几个字节?3个

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

public class Test {
    public static void main(String[] args) throws IOException {
        //使用文件名称创建流对象,构造方法中绑定要写入数据的目的地
        FileOutputStream fos = new FileOutputStream(new File("fos.txt"));
        byte[] b = {49,48,48};
        //写出字节数组数据
        fos.write(b);
        //关闭资源
        fos.close();
    }
}
//输出结果:100

3.2.3 写入指定长度字节数组
write(byte[] b, int off, int len) :把字节数组的一部分写入到文件。

  • int off:数组的开始索引
  • int len:写几个字节
import java.io.FileOutputStream;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        //使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("fos.txt");
        //字符串转为字节数组
        byte[] b = "abcdefg".getBytes();
        //写出从索引2开始,两个字节
        fos.write(b,2,2);
        //关闭资源
        fos.close();
    }
}
//输出结果:cd

3.2.4写入字符串
可以使用String类中的方法byte[] getBytes() 把字符串转换为字节数组。

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;

public class Test {
    public static void main(String[] args) throws IOException {
        //使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("a.txt");
        //字符串转换为字节数组
        byte[] bytes = "你好".getBytes();
        System.out.println(Arrays.toString(bytes));//[-28, -67, -96, -27, -91, -67]
        //写入字节数组数据
        fos.write(bytes);
        //释放资源
        fos.close();
    }
}

注: 由于IDEA所用的编码格式是UTF-8,所以两个汉字是6个字节。
3.3数据追加续写

方法名功能
public FileOutputStream(File file, boolean append)创建文件输出流以写入由指定的 File对象表示的 文件
public FileOutputStream(String name, boolean append)创建文件输出流以指定的名称写入文件

参数:

  • File file,String name:写入数据的目的地
  • boolean append:追加写开关(true:创建对象不会覆盖源文件,继续在文件的末尾追加写数据;false:创建一个新文件,覆盖源文件)
import java.io.FileOutputStream;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        //使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("fos.txt",true);
        //字符串转为字节数组
        byte[] b = "abcdefg".getBytes();
        //写出从索引2开始,两个字节
        fos.write(b,2,2);
        //关闭资源
        fos.close();
    }
}
//文件操作前:cd
//文件操作后:cdabcdefg

3.4写出换行
Windows系统里,换行符号是 \r\n。把
以指定是否追加续写了。

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

public class Test {
    public static void main(String[] args) throws IOException {
        //使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("fos.txt",true);
        //定义字节数据
        byte[] words = {97,98,99,100,101};
        //遍历数组
        for (byte b:words){
            //写出一个字节
            fos.write(words[b]);
            //写出一个换行,换行符号装成数组写出
            fos.write("\r\n".getBytes());
        }
        //关闭资源
        fos.close();
    }
}
/*
输出结果:
    a
    b
    c
    d
    e
 */

4.字节输入流【InputStream】

java.io.InputStream 抽象类是表示字节输入流的所有类的超类,可以读取字节信息到内存中。它定义了字节输入
流的基本共性功能方法。

方法名功能
public void close()关闭此输入流并释放与此流相关联的任何系统资源
public abstract int read()从输入流读取数据的下一个字节
public int read(byte[] b)从输入流中读取一些字节数,并将它们存储到字节数组 b中

5.FileInputStream–文件字节输入流

功能: 把硬盘文件中的数据读取到内存中使用。
5.1构造方法

方法名功能
FileInputStream(File file)通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系 统中的 File对象 file命名
FileInputStream(String name)通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件 系统中的路径名 name命名

参数: 读取文件的数据源(文件/文件的路径)
构造方法的作用:

  • 会创建一个FileInputStream对象。
  • 会把FileInputStream对象指向构造方法中要读取的文件。

注意:
当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有该文件,会抛出 FileNotFoundException 。

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class Test {
    public static void main(String[] args) throws FileNotFoundException {
        //使用File对象创建流对象
        File file = new File("a.txt");
        FileInputStream fis1 = new FileInputStream(file);
        
        //使用文件名称创建流对象
        FileInputStream fis2 = new FileInputStream("b.txt");
    }
}

5.2读取字节
读取数据的原理:(硬盘–>内存)
Java程序–>JVM–>OS->OS读取数据的方法–>读取文件
字节输出流的使用步骤:

  1. 创建FileInputStream对象,构造方法中绑定要读取的数据源
  2. 使用FileInputStream对象中的read方法,读取文件
  3. 释放资源

5.2.1读取字节数据
read 方法,每次可以读取一个字节的数据,提升为int类型,读取到文件末尾,返回 -1

import java.io.FileInputStream;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        //使用文件名创建流对象
        FileInputStream fis = new FileInputStream("a.txt");
        int len = 0;
        while ((len = fis.read()) != -1) {
            System.out.print((char) len);//abc
        }
        //释放资源
        fis.close();
    }
}

5.2.2使用字节数组读取
read(byte[] b) ,每次读取b的长度个字节到数组中,返回读取到的有效字节个数,读取到末尾时,返回-1
明确两件事:

  1. 方法参数byte[]的作用:①起到缓冲作用,存储每次读取到的多个字节;②数组的长度一般定义为1024(1kb)或者1024的整数倍。
  2. 方法返回值int是什么?每次读取的有效字节个数
import java.io.FileInputStream;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        //使用文件名称创建流对象
        FileInputStream fis = new FileInputStream("b.txt");
        byte[] bytes = new byte[1024];//存储读取到的多个字节
        int len = 0;//记录每次读取的有效字节个数
        while ((len = fis.read(bytes)) != -1) {
            //String(byte[] bytes,int offset,int length):把字节数组一部分转换为字符串,offset:数组的开始索引;length:转换的个数
            System.out.println(new String(bytes, 0, len));//ABCDE
        }
        //释放资源
        fis.close();
    }
}

在这里插入图片描述
5.3图片复制
在这里插入图片描述

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

public class Test {
    public static void main(String[] args) throws IOException {
        //1.创建一个字节输入流对象,构造方法中要绑定的数据源
        FileInputStream fis = new FileInputStream("c:\\1.jpg");
        //2.创建一个字节输出流对象,构造方法中要绑定的数据源
        FileOutputStream fos = new FileOutputStream("d:\\1.jpg");
        //3.使用数组缓冲读取多个字节,写入多个字节
        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len = fis.read(bytes))!= -1){
            //4.使用字节输出流的方法把读取到的字节写入到目的地文件中
            fos.write(bytes,0,len);
        }
        //5.释放资源
        fos.close();
        fis.close();
    }
}

四、字符流

当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。

1.字符输入流【Reader】

java.io.Reader 抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。它定义了字符输入流的基本共性功能方法。

方法名功能
public int read()从输入流读取一个字符
public int read(char[] cbuf)从输入流中读取一些字符,并将它们存储到字符数组cbuf中
public void close()关闭此流并释放与此流相关联的任何系统资源

1.1FileReader类

java.io.FileReader类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。

  1. 字符编码:字节与字符的对应规则。Windows系统的中文编码默认是GBK编码表。idea中UTF-8。
  2. 字节缓冲区:一个字节数组,用来临时存储字节数据。

构造方法:

方法名功能
FileReader(File file)创建一个新的FileReader ,给定要读取的File对象
FileReader(String fileName)创建一个新的FileReader ,给定要读取的文件的名称。

构造举例:

public class FileReaderConstructor throws IOException{
    public static void main(String[] args) {
        // 使用File对象创建流对象
        File file = new File("a.txt");
        FileReader fr = new FileReader(file);
      
        // 使用文件名称创建流对象
        FileReader fr = new FileReader("b.txt");
    }
}

1.2读取字符

read():返回读入的一个字符,如果达到文件末尾,返回-1

package Filele类;

import org.junit.Test;

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

/**
 * @BelongsProject: untitled
 * @BelongsPackage: Filele类
 * @Author: mcc
 * @CreateTime: 2020-11-23 07:51
 * @Description:
 */
public class FileResderWriterTest {
    /**
     * 将该Module下的hello.txt内容读入程序中,并输出到控制台
     */
    @Test
    public void testFileReader(){
        FileReader fr = null;
        try {
            //1.实例化File类的对象,指明要操作的文件
            File file = new File("hello.txt");
            //2.提供具体的流
            fr = new FileReader(file);
            //3.数据的读入
            int data;
            while ((data = fr.read()) != -1) {
                System.out.print((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.流的关闭
            try {
                if (fr != null)
                    fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

在这里插入图片描述
说明点:

  • 为了保证流资源一定可以执行关闭操作,需要使用try-catch-finally来处理
  • 读入的文件一定要存在,否则就会报FileNotFoundException

1.3使用字符数组读取

read(char[] cbuf) ,每次读取b的长度个字符到数组中,返回读取到的有效字符个数,读取到末尾时,返回-1 。

//对read()操作升级,使用read的重载方法
@Test
public void testFileReader1() {
    FileReader fr = null;
    try {
        //1.File类的实例化
        File file = new File("hello.txt");
        //2.FileReader流的实例化
        fr = new FileReader(file);
        //3.读入操作
        char[] arr = new char[5];
        int len;
        while ((len = fr.read(arr)) != -1) {
            for (int i = 0; i < len; i++) {
                System.out.print(arr[i]);
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (fr != null){
            //4.资源关闭
            try {
                fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

2.字符输入流

/**
 * 从内存中写出数据到硬盘的文件里
 */
@Test
public void testFileWriter() throws IOException {
    FileWriter fw = null;
    try {
        //1.提供File类的对象,指明写出到的文件
        File file = new File("hello1.txt");
        //2.提供FileWriter的对象,用于数据的写出
        fw = new FileWriter(file);
        //3.写出操作
        fw.write("I have a dream!");
        fw.write("You need to have a dream!");
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        //4.流资源的关闭
        try {
            if (fw != null)
                fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

说明:

  1. 输出操作对应的file可以不存在,并不会报异常
  2. file对应的硬盘中的文件,如果不存在,在输出的过程中会自动创建此文件
  3. file对应的硬盘中的文件,如果存在:如果流使用的构造器是FileWriter(file,false)FileWriter(file),则会对原有文件进行覆盖;如果流使用的构造器是FileWriter(file,true),不会对原文件覆盖,而是在原有文件基础上追加内容

3.文本文件复制

import org.junit.Test;

import java.io.*;

/**
 * @BelongsProject: untitled
 * @BelongsPackage: Filele类
 * @Author: mcc
 * @CreateTime: 2020-11-23 07:51
 * @Description:
 */
public class FileResderWriterTest {
    @Test
    public void testFileResderWriter() {
        FileReader fr = null;
        FileWriter fw = null;
        try {
            //1.创建File类的对象,指明读入和写出的文件
            File srcFile = new File("hello.txt");
            File destFile = new File("hello3.txt");
            //2.创建输入流和输出流的对象
            fr = new FileReader(srcFile);
            fw = new FileWriter(destFile);
            //3.数据的读入和写出操作
            char[] cbuf = new char[5];
            int len;//记录每次读入到cbuf数组中的字符的个数
            while ((len = fr.read(cbuf)) != -1) {
                fw.write(cbuf, 0, len);//每次写出len个字符
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭流资源
            try {
                if (fw != null)
                    fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (fr != null)
                        fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值